{}+[]是什么?详解js的“+”号运算符

在JS中的运算符共同的情况中,(+)符号是很常见的一种,它有以下的使用情况:

  • 数字的加法运算,二元运算

  • 字符串的连接运算,二元运算,最高优先

  • 正号,一元运算,可延伸为强制转换其他类型的运算元为数字类型

当然,如果考虑多个符号一起使用时,(+=)与(++)又是另外的用途。

另一个常见的是花括号({}),它有两个用途也很常见:

  • 对象的字面文字定义

  • 区块语句

所以,要能回答这个问题,要先搞清楚重点是什么?

第一个重点是:

加号(+)运算在JS中在使用上的规定是什么。

第二个重点则是:

对象在JS中是怎么转换为原始数据类型的值的。

加法运算符会触发三种类型转换:

  • 转换为原始值
  • 转换为数字
  • 转换为字符串
- 通过 ToPrimitive() 将值转换为原始值

ToPrimitive(input,PreferredType?)
(可选参数 PreferredType 可以是 Number 或者 String。 它只代表了一个转换的偏好,转换结果不一定必须是这个参数所指的类型(汗),但转换结果一定是一个原始值。 如果 PreferredType 被标志为 Number,则会进行下面的操作来转换input)
1.如果 input 是个原始值,则直接返回它。
2.否则,如果 input 是一个对象。则调用 obj.valueOf() 方法。 如果返回值是一个原始值,则返回这个原始值。
3.否则,调用 obj.toString() 方法。 如果返回值是一个原始值,则返回这个原始值。
4.否则,抛出 TypeError 异常。

如果 PreferredType 被标志为 String,则转换操作的第二步和第三步的顺序会调换。 如果没有 PreferredType 这个参数,则 PreferredType 的值会按照这样的规则来自动设置:

  • Date 类型的对象会被设置为 String
  • 其它类型的值会被设置为 Number

当“+”号左右两边都是数值时,有以下特殊情况

1.当有一个操作数是NAN,则结果是NAN
2.如果是Infinity加上Infinity,则结果是Infinity (Infinity表示无穷大)
3、如果是 - Infinity + -Infinity,则结果是-Infinity (Infinity表示无穷大)
4、如果是 Infinity + -Infinity,则结果是 NaN
5、 +0 + -0 = +0
6、 -0 + -0 = -0
7、+0 + +0 = +0

其他实例

字符串 + 其他原始类型

字符串在加号运算有最高的优先运算,与字符串相加必定是字符串连接运算(concatenation)。所有的其他原始数据类型转为字符串,可以参考ECMAScript标准中的ToString对照表,以下为一些简单的例子:
在这里插入图片描述

数字 + 其他的非字符串的原始数据类型

数字与其他类型作相加时,除了字符串会优先使用字符串连接运算(concatenation)的,其他都要依照数字为优先,所以除了字符串之外的其他原始数据类型,都要转换为数字来进行数学的相加运算。如果明白这项规则,就会很容易的得出加法运算的结果。

所有转为数字类型可以参考ECMAScript标准中的ToNumber对照表,以下为一些简单的例子:
在这里插入图片描述

数字/字符串以外的原始数据类型作加法运算**

当数字与字符串以外的,其他原始数据类型直接使用加号运算时,就是转为数字再运算,这与字符串完全无关。
注意:

Number(undefiened)      //NaN
Number(null)                //0

在这里插入图片描述

空数组+空数组
[] +[]           // " "

两个数组相加,依然按照valueOf -> toString的顺序,但因为valueOf是数组本身,所以会以toString的返回值才是原始数据类型,也就是空字符串,所以这个运算相当于两个空字符串在相加,依照加法运算规则第2步骤,是字符串连接运算(concatenation),两个空字符串连接最后得出一个空字符串。

空对象 + 空对象

在这里插入图片描述
两个空对象相加,依然按照valueOf -> toString的顺序,但因为valueOf是对象本身,所以会以toString的返回值才是原始数据类型,也就是"[object Object]“字符串,所以这个运算相当于两个”[object Object]"字符串在相加,依照加法运算规则第2步骤,是字符串连接运算(concatenation),最后得出一个"object Object"字符串。

但是这个结果有异常,上面的结果只是在Chrome浏览器上的结果(v55),怎么说呢?

有些浏览器例如Firefox、Edge浏览器会把{} + {}直译为相当于+{}语句,因为它们会认为以花括号开头({)的,是一个区块语句的开头,而不是一个对象字面量,所以会认为略过第一个{},把整个语句认为是个+{}的语句,也就是相当于强制求出数字值的Number({})函数调用运算,相当于Number("[object Object]")运算,最后得出的是NaN。

特别注意: {} + {}在不同的浏览器有不同结果
如果在第一个(前面)的空对象加上圆括号(()),这样JS就会认为前面是个对象,就可以得出同样的结果:

({}) + {}
"[object Object][object Object]"

: 上面说的行为这与加号运算的第一个(前面)的对象字面值是不是个空对象无关,就算是里面有值的对象字面,例如{a:1, b:2},也是同样的结果。

注: 上面说的Chrome浏览器是在v55版本中的主控台直接运行的结果。其它旧版本有可能并非此结果。

空对象 + 空数组

上面同样的把{}当作区块语句的情况又会发生,不过这次所有的浏览器都会有一致结果,如果{}(空对象)在前面,而[] (空数组)在后面时,前面(左边)那个运算元会被认为是区块语句而不是对象字面量。
所以{} + []相当于+[]语句,也就是相当于强制求出数字值的Number([])运算,相当于Number("")运算,最后得出的是0数字。

> {} + []
0

> [] + {}
"[object Object]"

特别注意: 所以如果第一个(前面)是{}时,后面加上其他的像数组、数字或字符串,这时候加号运算会直接变为一元正号运算,也就是强制转为数字的运算。这是个陷阱要小心。

Date类型

Date对象的valueOf与toString的两个方法的返回值:

  • valueOf方法返回值: 给定的时间转为UNIX时间(自1 January 1970 00:00:00 UTC起算),但是以微秒计算的数字值

  • toString方法返回值: 本地化的时间字符串

Date对象上面有提及是首选类型为"字符串"的一种异常的对象,这与其他的对象的行为不同(一般对象会先调用valueOf再调用toString),在进行加号运算时时,它会优先使用toString来进行转换,最后必定是字符串连接运算(concatenation),例如以下的结果:

1 + (new Date())
> "1Sun Nov 27 2016 01:09:03 GMT+0800 (CST)"

要得出Date对象中的valueOf返回值,需要使用一元加号(+),来强制转换它为数字类型,例如以下的代码:

> +new Date()
1480180751492
Symbols类型

S6中新加入的Symbols数据类型,它不算是一般的值也不是对象,它并没有内部自动转型的设计,所以完全不能直接用于加法运算,使用时会报错。

总结

  • {} + {}的结果是会因浏览器而有不同结果,Chrome(v55)中是[object Object][object Object]字符串连接,但其它的浏览器则是认为相当于+{}运算,得出NaN数字类型。

  • {} + []的结果是相当于+[],结果是0数字类型。

分享一篇讲得很好的文章,也是本文参考的地址:https://segmentfault.com/a/1190000008038678

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值