JavaScript 加號運算符詳解

来源:http://www.cnblogs.com/polk6/archive/2017/08/24/js-adv-addopr.html
-Advertisement-
Play Games

介紹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

 

==================================系列文章==========================================

本篇文章:3.11 JavaScript 加號運算符詳解

Web開發之路系列文章

 
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 設計模式(0)簡單工廠模式 設計模式(1)單例模式(Singleton) 設計模式(2)工廠方法模式(Factory Method) 設計模式(3)抽象工廠模式(Abstract Factory) 源碼地址 0 建造者模式簡介 0.0 建造者模式定義 建造者模式是一種常見的創建型模式,也稱生成器模式 ...
  • ...
  • <a href="" id="submitbtn" onclick="javascript:validateCode();return false;" tabindex="4"></a> 要在onclick中加入return false ...
  • CSS根據屏幕解析度寬度自動適應的辦法 第一種辦法是js選擇CSS CSS根據屏幕解析度寬度自動適應的辦法 第一種辦法是js選擇CSS CSS根據屏幕解析度寬度自動適應的辦法 第一種辦法是js選擇CSS <SCRIPT language=JavaScript><!-- Beginif (screen ...
  • slice substring 從開始位置到結束位置前的字元串 substr 返回開始位置後的長度的字元串 var str="hello world"; str.slice(3); // "lo world" str.substring(3); // "lo world" str.substr(3) ...
  • 下載插件 插件地址:http://silviomoreto.github.io/bootstrap-select/ 下載好後引用css和js文件 使用方法 設置預設選中方法 其他配置項和方法 可以查看官網 ...
  • 在html5新增的classList之前, 操作元素的class用的是className這個屬性,而如果要向jquery封裝的hasClass, removeClass, addClass, toggleClass一樣優雅的操作calssName, 在以前我們要對className封裝處理,如下, ...
  • 1.定義函數,函數中定義類對象 f1=function(){ //定義類 function Pannel(name){ this.name = name; this.print = function(){ console.info(this.name); }; } //擴展類方法成員 Pann... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...