有一道面試題是:
實現(xiàn)一個函數(shù)告希,運算結(jié)果可以滿足如下預(yù)期結(jié)果:
add(1)(2) //3
add(1,2,3)(10) //16
add(1)(2)(3)(4)(5) //15
其中一種解法:
function add(){
console.log("進入add");
var args = Array.prototype.slice.call(arguments);
console.log(args);
var fn = function () {
var arg_fn = Array.prototype.slice.call(arguments);
console.log('調(diào)用fn');
console.log(arg_fn);
return add.apply(null,args.concat(arg_fn));
}
fn.valueOf = function () {
console.log('調(diào)用valueOf()');
return args.reduce(function (a,b) {
console.log('調(diào)用valueOf(),返回%d+%d=%d',a,b,a+b);
return a+b;
})
}
return fn;
}
console.log(add(2)(3,4);
// add(1)(2);
// add(3,4,5)(6);
剛看到這個解決辦法會覺得很奇怪,fn.valueOf()沒有被調(diào)用過纬向,這樣寫怎么能成功解決呢迈倍?
原因:
JavaScript調(diào)用valueOf()方法把對象轉(zhuǎn)換成原始類型的值(數(shù)值伤靠、字符串和布爾值)。并且往往valueOf()方法會被JavaScript自動調(diào)用啼染。
valueOf()和toString()在特定場合下會自動調(diào)用Q绾稀!迹鹅!
下面來說一說類型轉(zhuǎn)換:
原始類型
JavaScript的幾種原始類型卦洽,除去Object和Symbol,有以下幾種:
- Number
- String
- Boolean
- Undefined
- Null
在JavaScript進行對比或者各種運算的時候會把對象轉(zhuǎn)換成這些類型斜棚,從而進行后續(xù)操作阀蒂。
String類型轉(zhuǎn)換
在某個操作或者運算需要字符串而該對象又不是字符串的時候,會觸發(fā)該對象的String轉(zhuǎn)換弟蚀,會將非字符串的類型嘗試自動轉(zhuǎn)換為String類型蚤霞。系統(tǒng)內(nèi)部會自動調(diào)用toString函數(shù)。
var obj = {name:'Wonder'};
var str = '123'+obj;
console.log(str); //123[object Object]
轉(zhuǎn)換規(guī)則:
- 如果toString方法存在并且返回原始類型义钉,返回toString的結(jié)果昧绣。
- 如果toString方法不存在或者返回的不是原始類型,調(diào)用valueOf方法捶闸,如果valueOf方法存在夜畴,并且返回的是原始類型數(shù)據(jù),返回valueOf的結(jié)果
- 其他情況删壮,拋出錯誤斩启。
上面的例子實際上是:
var obj = {name:'Wonder'};
var str = '123'+obj.toString();
//obj.toString的值是[object Object]
如果我們改寫對象的toString,valueOf方法:
var obj = {
toString:function(){
console.log('調(diào)用了toString');
return {};
},
valueOf:function(){
console.log('調(diào)用了valueOf');
return '10';
}
}
console.log(obj);
//調(diào)用了toString
//調(diào)用了valueOf
//10
Number類型轉(zhuǎn)換
以下會發(fā)生Number類型轉(zhuǎn)換:
- 調(diào)用Number()函數(shù)醉锅,強制進行Number類型轉(zhuǎn)換
- 調(diào)用Math.sqrt()這類參數(shù)需要Number類型的方法
- obj == 1,進行對比的時候
- obj+1发绢,進行運算的時候
與String類型轉(zhuǎn)換相似硬耍,但是Number類型剛好反過來垄琐,先查詢自身的valueOf方法,再查詢自己toString方法经柴。
轉(zhuǎn)換規(guī)則:
- 如果valueOf方法存在并且返回原始類型狸窘,返回valueOf的結(jié)果。
- 如果valueOf方法不存在或者返回的不是原始類型坯认,調(diào)用toString方法翻擒,如果toString方法存在,并且返回的是原始類型數(shù)據(jù)牛哺,返回toString的結(jié)果
- 其他情況陋气,拋出錯誤。
Boolean轉(zhuǎn)換
什么時候會進行布爾轉(zhuǎn)換呢引润?
- 布爾比較時
- if(obj),while(obj)等判斷時
轉(zhuǎn)換規(guī)則:
除了下述 6 個值轉(zhuǎn)換結(jié)果為 false巩趁,其他全部為 true:
- undefined
- null
- -0
- 0或+0
- NaN
- ”(空字符串)