js中加號+ 運(yùn)算符可以用在一元運(yùn)算 與 二元運(yùn)算?
1,? 一元運(yùn)算請況
? ??語法:?+ Expression
? ??????????????+'號運(yùn)算符作為一元運(yùn)算符時,Expression將進(jìn)行ToNumber()操作
? ? 經(jīng)常使用 +a 類似的形式對變量a進(jìn)行類型轉(zhuǎn)換 ,如下:
? ? ?const a = '1';
? ? ? +a? // 輸出為1 (變?yōu)閚umber類型);
ToNumber( argument )轉(zhuǎn)換方式:
Undefined:? return NaN,
Null:return +0,
Bollean: true return 1,false return 0,
Number:? return value
String:??若字符串為純數(shù)字時返回轉(zhuǎn)換后的數(shù)字;非純數(shù)字返回NaN
Symbol? 拋出?TypeError 異常
Object? ?進(jìn)行以下步驟:
? ? ? ? ? ? ?1.先進(jìn)行ToPrimitive(argument, hint Number)得到rs;? ?2.然后返回 ToNumber(rs)的結(jié)果。
語法:ToPrimitive ( input [, PreferredType] )
參數(shù):
①參 input :傳入的值。
②參數(shù) PreferredType :可選,需要被轉(zhuǎn)換的類型。'+'加號作為一元運(yùn)算符時,此值為“number”;而作為二元運(yùn)算符時,未傳遞此值,以默認(rèn)的“default”代替。
2. 二元運(yùn)算符
2.1 解析步驟
簡單概括為下面4個步驟:
1) 值進(jìn)行GetValue()操作。
2) 值進(jìn)行ToPrimitive()操作,
3) 若一方為String類型,2個值都進(jìn)行ToString()轉(zhuǎn)換,最后進(jìn)行字符串連接操作。
4) 若都不是String類型,2個值都進(jìn)行ToNumber()轉(zhuǎn)換,最后進(jìn)行算數(shù)加法運(yùn)算。
2.2.1 方法簽名
語法:ToPrimitive ( input [, PreferredType] )
參數(shù):
①參?input :傳入的值。
②參數(shù)?PreferredType :可選,需要被轉(zhuǎn)換的類型。'+'加號作為一元運(yùn)算符時,此值為“number”;而作為二元運(yùn)算符時,未傳遞此值,以默認(rèn)的“default”代替。
2.2.2 解析說明
ToPrimitive()的詳細(xì)解析過程可以看這里:
http://www.ecma-international.org/ecma-262/6.0/#sec-toprimitive
簡化為以下步驟:
(PreferredType是為 非基礎(chǔ)類型 決定是優(yōu)先使用valueOf方法還是toString方法,對基礎(chǔ)類型無效),指定為number優(yōu)先使用valueOf方法,指定string,優(yōu)先使用toString方法
1) 若input類型為原始值(如:Undefined、Null、Boolean、Number、String、Symbol),直接返回input的本身。 直接忽略PreferredType
2) 若input類型為object(如:Array、Object、Date),將根據(jù)第②個參數(shù) PreferredType 的值進(jìn)行以下操作:
就像之前講的,'+'加號作為一元運(yùn)算符時, 傳遞參數(shù) PreferredType 的值為“number”;而作為二元運(yùn)算符時,未傳遞此值時以默認(rèn)的“default”代替。

在上面的圖中,只看到 PreferredType 的值為“number” 或 “string” 時才進(jìn)行解析,那么默認(rèn)的“default”表示什么呢?
ps:Date類型內(nèi)部重寫了@@toPrimitive()方法,將“default”設(shè)置為“string”,而其他內(nèi)置的對象都將“default”設(shè)置為“number”。
Date.prototype[@@toPrimitive]:
http://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype-@@toprimitive
2.3 示例
1) String + String
說明:進(jìn)行字符串連接操作
'a' + 'b'; // => 'ab'
'1' + '2'; // => '12'
2) Number + Number
說明:進(jìn)行算數(shù)的加法操作
1 + 2; // => 3
3) Number + String or String + Number
說明:Number類型的值先進(jìn)行ToString()轉(zhuǎn)換,隨后再與另一個String類型的值進(jìn)行拼接操作
1 + '0'; // => '10'
1 + '0a'; // => '10a'
'1' + 2; // => 12
4) Array + String or Array + Number
說明:Array類型進(jìn)行ToPrimitive()轉(zhuǎn)換時,先執(zhí)行valueOf(),因其返回一個object類型的值,所以又執(zhí)行了toString()方法。
var tmpList = ['a', 'b', 'c'];
tmpList.valueOf(); // => ["a", "b", "c"]? 輸出自身
tmpList.toString(); // a,b,c
// 1.Array + String
tmpList + 'd'; // => a,b,cd
// 2.重寫Array的valueOf()方法,使其返回一個非object
Array.prototype.valueOf = function (e) {
? ? return this.join('-');
}
tmpList + 'd'; // => a-b-cd
5) Date + String or Date + Number
說明:上面已經(jīng)講過,Date類型重寫了ToPrimitive(),所以先調(diào)用toString(),若返回值為object,再調(diào)用valueOf()。
var dt = new Date();
dt.valueOf(); // => 1503501745901
dt.toString(); // Wed Aug 23 2017 23:22:25 GMT+0800 (中國標(biāo)準(zhǔn)時間)
// 1.Date + String : dt直接使用了dt.toString()方法
dt + 'd'; // => Wed Aug 23 2017 23:22:25 GMT+0800 (中國標(biāo)準(zhǔn)時間)d
// 2.重寫Date的toString()方法,使其返回一個object的值
Date.prototype.toString = function (e) {
? ? return { year: this.getFullYear() };
}
// 略過了 dt.toString(),調(diào)用了 dt.valueOf()
dt + 'd'; // => 1503501745901d
End