将介绍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; |
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // 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
说明:进行字符串连接操作
1 2 | 'a' + 'b' ; // => 'ab' '1' + '2' ; // => '12' |
2) Number + Number
说明:进行算数的加法操作
1 | 1 + 2; // => 3 |
3) Number + String or String + Number
说明:Number类型的值先进行ToString()转换,随后再与另一个String类型的值进行拼接操作
1 2 3 | 1 + '0' ; // => '10' 1 + '0a' ; // => '10a' '1' + 2; // => 12 |
4) Array + String or Array + Number
说明:Array类型进行ToPrimitive()转换时,先执行valueOf(),因其返回一个object类型的值,所以又执行了toString()方法。
1 2 3 4 5 6 7 8 9 10 11 12 | 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()。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!