+号运算规则


基础类型相加

字符串的优先级高,当遇到一边是字符串时,都转换为字符串再拼接。不是字符串情况下,尝试把两边的操作变量转换为数字,如果两边都转换成功,则进行数字加法。

注:这里转换为数字调用的是`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进行“+”号运算时也遵循先转换为字符串后再运算。
FunctiontoString 方法不是返回 [object Object],而是将整个方法体返回为字符串,连换行和缩进都完整保持。 FunctiontoString,返回的是定义函数时,等号右边的全部内容字符串。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) => {}'

总结

  • 都是基础类型,存在字符串时,两边转为字符串再运算,不存在字符串,两边转为数字再运算
  • 存在引用对象,两边转换为字符串后再运算