关于面试中经常遇到的 x + y 的值问题,一直是比较蛋疼的事儿,这里主要针对这两个比较常见的操作符 “ + ” 进行整理
+ 操作符
我们平常最常用到的字符串相加和数值相加的问题,我这里就简单的带过。
例: 我们现在要求 x + y 的值
最常用的两种情况:
- x 和 y 均为数值 : x = 1 , y = 2,则 x + y = 3
- x 和 y 均为字符串: x = ‘你’ y = ‘好’,则 x + y = ‘你好’
这俩种情况是最常见的,并且只要涉及到NaN的计算,无论怎样结果都是NaN。其他的情况估计只有在面试题里会见到了。开发中要是谁特么乱用这个估计会被打死,现在我们来说说面试中关于 + 操作符的其他情况。
Infinity
- Infinity + Infinity = Infinity
- -Infinity + -Infinity = -Infinity
- Infinity + -Infinity = NaN
前两种都好理解,最后一种乍一眼感觉可能是 0。但实际上结果是NaN。所以可以这么理解,涉及到 Infinity 的加减,你感觉可以得到一个常数,肯定得不到,结果都是NaN,例如下面几种情况
- Infinity * 0 —— 感觉结果是0,实际上是 NaN
- Infinity / Infinity —— 感觉结果是1,实际上是 NaN
- Infinity + -Infinity —— 感觉结果是0,实际上是 NaN
- Infinity - Infinity —— 感觉结果是0,实际上是 NaN
数字 + 字符串
很简单,会把数字转换成字符串,然后再相加
“1” + 123 => “1” + “123” => “1123”
基本数据类型 + 基本数据类型 (非字符串)
基本数据类型(先不说字符串)和数字相加或者自己加自己时,会按照如下逻辑调用自己的Number方法
- 把 null 转成 0
- 把 undefined 转成NaN
- 把 true 转成 1 , false 转成 0
false + 1 // 1
true + 1 // 2
false + false // 0
true + true // 2
undefined + undefined // NaN
undefined + null // NaN
null + 123 // 123
false + null // 0
其他情况会调用toString(),然后再执行字符串运算
false + "1" // "false1"
true + {} // "true[object Object]"
引用数据类型(对象) + X
对象 + X 会调用对象的toString()方法,将返回的值来进行相加
情况一:大部分对象
{} + 1 // "[object Object]1"
{} + {} // "[object Object][object Object]"
[] + {} // "[object Object]"
关于第三行的例子,这里有个比较好玩的现象就是空数组的toString()方法,得到的是空字符串,Number方法也是,会先调用toString()方法,然后将得到的值转成数字
[].toString() // ""
[1,2,3].toString() // "1,2,3"
Number([]) // 0
Number([123]) // 123 ([123] --> "123" --> 123)
Number([123, 123]) // NaN ([123,123] --> "123,123" --> 123)
情况二:指定valueOf的对象
对于指定valueOf的对象,先看下面几个例子
var obj = {
valueOf: () => 3
};
var obj1 = {
valueOf: () => false
};
var obj2 = {
valueOf: () => "1"
};
var obj3 = {
valueOf: () => null
};
var obj4 = {
valueOf: () => undefined
};
obj + 3; // 6
obj1 + 3; // 3
obj2 + 3; // "13"
obj3 + 3; // 3
obj4 + 3; // NaN
这里会先调用对象的valueOf方法,如果返回的值是 基本数据类型(number, string, boolean, undifined, null),则用返回的基本数据类型的值来进行接下来的运算。
其他情况直接调用返回值的toString()方法,再执行字符串相加。
var obj = {
valueOf: () => obj
};
var obj1 = {
valueOf: () => {}
};
obj + 3; // "[object Object]3"
obj1 + 3; // "[object Object]3"
碰到的一些沙雕的问题
本人喜欢在Chrome的控制台里来进行一些调试,有一次
emmm,如果按照上面的说法,理论上结果应该是。
{} 调用toString()方法得到的结果是 “[object Object]”
[] 调用toString()方法得到的结果是 “”
两个相加正常情况下应该是 “[object Object]”
但为啥是 0 呢?
看了下图应该就明白了
在JavaScript解析过程中。图一中的 {} 其实并不是对象,而是一个代码块,不参与运算,控制台打印的是 + [] 的值,所以是0
这两种表达理论上是一样的,所以会出现上述问题
这种方式同理,带上分号 把第一个 {} 解析成了代码块,所以最后的值就是 + {} 得到 NaN