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;
2.然后返回 ToNumber(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

  1. Let lref be the result of evaluating AdditiveExpression.

  2. Let lval be GetValue(lref).

  3. ReturnIfAbrupt(lval).

  4. Let rref be the result of evaluating MultiplicativeExpression.

  5. Let rval be GetValue(rref).

  6. ReturnIfAbrupt(rval).

  7. Let lprim be ToPrimitive(lval).

  8. ReturnIfAbrupt(lprim).

  9. Let rprim be ToPrimitive(rval).

  10. ReturnIfAbrupt(rprim).

  11. If Type(lprim) is String or Type(rprim) is String, then

    1. Let lstr be ToString(lprim).

    2. ReturnIfAbrupt(lstr).

    3. Let rstr be ToString(rprim).

    4. ReturnIfAbrupt(rstr).

    5. Return the String that is the result of concatenating lstr and rstr.

  12. Let lnum be ToNumber(lprim).

  13. ReturnIfAbrupt(lnum).

  14. Let rnum be ToNumber(rprim).

  15. ReturnIfAbrupt(rnum).

  16. 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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM