介紹JavaScript中 '+'加號運算符在一元、二元運算時的表現。 ...
將介紹JavaScript中 '+'加號運算符在一元、二元運算時的表現。
目錄
1. 一元運算符
2. 二元運算符
1. 一元運算符
語法: + Expression
說明:'+'號運算符作為一元運算符時,Expression將進行ToNumber()操作。
ToNumber( argument )轉換方式:
argument類型 | 返回值 |
Undefined | return NaN |
Null | return +0 |
Boolean | true return 1; false return 0; |
Number | return value |
String | 若字元串為純數字時返迴轉換後的數字;非純數字返回NaN |
Symbol | 拋出 TypeError 異常 |
Object |
進行以下步驟: 1.先進行ToPrimitive(argument, hint Number)得到rs; |
示例:
// Undefined + undefined; // => NaN // Null + null; // => 0 // Boolean + true; // => 1 + false; // => 0 // String + '1'; // => 1 + '-1'; // => -1 + 'a1'; // => NaN // Object + {}; // => NaN + { valueOf: function () { return 0 } }; // => 0
2. 二元運算符
語法: AdditiveExpression + MultiplicativeExpression
2.1 解析步驟
首先看下ECMAScript 2015(ES6)關於加法運算符的說明:
AdditiveExpression : AdditiveExpression +
MultiplicativeExpression
-
Let lref be the result of evaluating AdditiveExpression.
-
Let lval be GetValue(lref).
-
ReturnIfAbrupt(lval).
-
Let rref be the result of evaluating MultiplicativeExpression.
-
Let rval be GetValue(rref).
-
ReturnIfAbrupt(rval).
-
Let lprim be ToPrimitive(lval).
-
ReturnIfAbrupt(lprim).
-
Let rprim be ToPrimitive(rval).
-
ReturnIfAbrupt(rprim).
-
Let lstr be ToString(lprim).
-
ReturnIfAbrupt(lstr).
-
Let rstr be ToString(rprim).
-
ReturnIfAbrupt(rstr).
-
Return the String that is the result of concatenating lstr and rstr.
-
Let lnum be ToNumber(lprim).
-
ReturnIfAbrupt(lnum).
-
Let rnum be ToNumber(rprim).
-
ReturnIfAbrupt(rnum).
-
Return the result of applying the addition operation to lnum and rnum. See the Note below 12.7.5.
鏈接:http://www.ecma-international.org/ecma-262/6.0/#sec-addition-operator-plus
簡單概括為下麵4個步驟:
1) 值進行GetValue()操作。
2) 值進行ToPrimitive()操作,
3) 若一方為String類型,2個值都進行ToString()轉換,最後進行字元串連接操作。
4) 若都不是String類型,2個值都進行ToNumber()轉換,最後進行算數加法運算。
2.2 ToPrimitive(value)方法說明
在上面的步驟中,重點說明是其中的ToPrimitive()方法,除了在'+'號運算符用到此方法外,ToNumber()、ToString()等也都用到此方法。
2.2.1 方法簽名
語法:ToPrimitive ( input [, PreferredType] )
參數:
①參 input :傳入的值。
②參數 PreferredType :可選,需要被轉換的類型。'+'加號作為一元運算符時,此值為“number”;而作為二元運算符時,未傳遞此值,以預設的“default”代替。
2.2.2 解析說明
ToPrimitive()的詳細解析過程可以看這裡:http://www.ecma-international.org/ecma-262/6.0/#sec-toprimitive
簡化為以下步驟:
1) 若input類型為原始值(如:Undefined、Null、Boolean、Number、String、Symbol),直接返回input的本身。
2) 若input類型為object(如:Array、Object、Date),將根據第②個參數 PreferredType 的值進行以下操作:
就像之前講的,'+'加號作為一元運算符時, 傳遞參數 PreferredType 的值為“number”;而作為二元運算符時,未傳遞此值時以預設的“default”代替。
在上面的圖中,只看到 PreferredType 的值為“number” 或 “string” 時才進行解析,那麼預設的“default”表示什麼呢?
重點來了:Date類型內部重寫了@@toPrimitive()方法,將“default”設置為“string”,而其他內置的對象都將“default”設置為“number”。
Date.prototype[@@toPrimitive]:http://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype-@@toprimitive
2.3 示例
1) String + String
說明:進行字元串連接操作
'a' + 'b'; // => 'ab' '1' + '2'; // => '12'
2) Number + Number
說明:進行算數的加法操作
1 + 2; // => 3
3) Number + String or String + Number
說明:Number類型的值先進行ToString()轉換,隨後再與另一個String類型的值進行拼接操作
1 + '0'; // => '10' 1 + '0a'; // => '10a' '1' + 2; // => 12
4) Array + String or Array + Number
說明:Array類型進行ToPrimitive()轉換時,先執行valueOf(),因其返回一個object類型的值,所以又執行了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
說明:上面已經講過,Date類型重寫了ToPrimitive(),所以先調用toString(),若返回值為object,再調用valueOf()。
var dt = new Date(; dt.valueOf(); // => 1503501745901 dt.toString(); // Wed Aug 23 2017 23:22:25 GMT+0800 (中國標準時間) // 1.Date + String : dt直接使用了dt.toString()方法 dt + 'd'; // => Wed Aug 23 2017 23:22:25 GMT+0800 (中國標準時間)d // 2.重寫Date的toString()方法,使其返回一個object的值 Date.prototype.toString = function (e) { return { year: this.getFullYear() }; } // 略過了 dt.toString(),調用了 dt.valueOf() dt + 'd'; // => 1503501745901d
==================================系列文章==========================================
本篇文章:3.11 JavaScript 加號運算符詳解