+号运算规则
基础类型相加
字符串的优先级高,当遇到一边是字符串时,都转换为字符串再拼接。不是字符串情况下,尝试把两边的操作变量转换为数字,如果两边都转换成功,则进行数字加法。
注:这里转换为数字调用的是`Number`,字符串调用的是`toString`,有括号时括号优先
```js 1 + 1 = 2 1 + '2' = '12' 1 + false = 1 1 + null = 1 1 + undefined = NaN false + false = 0 false + null = 0 false + undefined = NaN null + undefined = NaN (1 + 1) + '1' = '21' NaN + 1 = NaN NaN + '1' = NaN1 ``` 引用对象类型相加
Object 对象在进行 "+" 操作时,会先调用自己的 toString 方法,再进行字符串拼接
[] + [] = ''
[] + [[1]] = '1'
[] + [{ a: 1}] = '[object object]' // {a: 1}调用toString()先转为[object object]
[] + ({}) = '[object object]'
({}) + [1] = '[object object]1'
({}) + ({}) = '[object object][object object]'
({}) + ({a: [1]}) = '[object object][object object]'
+{} = 'NaN' // 由于控制台解析导致,请看以下解释
注:console.log({}+{})得到的这样的结果,但是,在有些浏览器例如Firefox、Edge控制台直接输入{}+{},会得到NaN,因为浏览器会把{} + {}直译为相当于+{}语句,因为它们会认为以花括号开头({)的,是一个区块语句的开头,而不是一个对象字面量,所以会认为略过第一个{},把整个语句认为是个+{}的语句,也就是相当于强制求出数字值的Number({})函数调用运算,相当于Number("[object Object]")运算,最后得出的是NaN。如果加上圆括号({}) + {},则可以避免这样的问题。
基础类型 + 引用对象类型
基础类型和引用对象类型进行 “+” 号运算时,两遍都转换为字符串后再进行比较。
1 + [] = '1'
1 + ({}) = '1[object object]'
'2' + [] = '2'
'2' + ({}) = '2[object object]'
false + [] = 'false'
false + [{}] = 'false[object object]'
false + ({}) = 'false[object object]'
null + [] = 'null'
null + ({}) = 'null[object object]'
null + [{}] = 'null[object object]'
undefined + [] = 'undefined'
undefined + ({}) = 'undefined[object object]'
undefined + [{}] = 'undefined[object object]'
NaN + [] = 'NaN'
// 复杂例子
[1,2,['abc'],[4,5,{ name:'abe' }]].toString() = '1,2,abc,4,5,[object object]'
函数对象toString结果
Function进行“+”号运算时也遵循先转换为字符串后再运算。Function 的 toString 方法不是返回 [object Object],而是将整个方法体返回为字符串,连换行和缩进都完整保持。 Function 的 toString,返回的是定义函数时,等号右边的全部内容字符串。func3等价于func1。
let func1 = function(){} // func1.toString() 结果为 'function(){}'
let func2 = (a, b) => {} // func2.toString() 结果为 '(a, b) => {}'
function func3(){} // func3.toString() 结果为 'function func3(){}'
1 + func1 // '1function(){}'
({}) + func1 // '[object Object]function(){}'
false + func1 // 'falsefunction(){}'
1 + func2 // '1(a, b) => {}'
总结
- 都是基础类型,存在字符串时,两边转为字符串再运算,不存在字符串,两边转为数字再运算
- 存在引用对象,两边转换为字符串后再运算
