在javascript中添加两个空白对象或空白数组

inv*_*ess 11 javascript type-conversion

当我找到以下控制台输出时,我只是在玩javascript:

  1. [] + [] //输出:""
  2. [] + {} //输出:[object Object]
  3. {} + [] //输出:0
  4. {} + {} //输出:NaN

有谁能请解释这些输出背后的逻辑.我觉得这是一个非常奇怪的行为,但我猜它可能有一些逻辑.

提前致谢.

Ale*_*har 9

预期成绩

当您添加两个数组时,一切都按预期工作:

[] + []//output''
Run Code Online (Sandbox Code Playgroud)

转换[]为原语首先尝试valueOf()返回数组本身(this):

var arr = [];
arr.valueOf() === arr
true
Run Code Online (Sandbox Code Playgroud)

由于该结果不是原语,因此将调用toString()并返回空字符串(这是一个原语).因此,结果[] + []是两个空字符串的串联.

{} + [] // output: 0
Run Code Online (Sandbox Code Playgroud)

添加数组和对象也符合我们的期望:

 [] + {}//output '[object Object]'
Run Code Online (Sandbox Code Playgroud)

说明:将空对象转换为字符串会产生以下结果.

 String({})//output: '[object Object]'
Run Code Online (Sandbox Code Playgroud)

因此,先前的结果是通过连接""和创建的"[object Object]".

出乎意料的结果

如果+的第一个操作数是一个空的对象文字(在Firefox控制台上看到的结果),事情会变得奇怪:

{} + {}//output: NaN
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?问题是JavaScript将第{}一个解释为空代码块并忽略它.的NaN因此是通过评估计算+{}(加上之后是第二{}).你在这里看到的加号不是二元加法运算符,而是一个一元前缀运算符,它将操作数转换为数字,方法与之相同Number().例如:

+"3.65"
3.65
Run Code Online (Sandbox Code Playgroud)

以下表达式都是等效的:

+{}
Number({})
Number({}.toString())  // {}.valueOf() isn’t primitive
Number("[object Object]")
NaN
Run Code Online (Sandbox Code Playgroud)

为什么第一个被{}解释为代码块?因为完整的输入被解析为语句,并且语句开头的花括号被解释为启动代码块.因此,您可以通过强制将输入解析为表达式来修复问题:

({} + {})//output: '[object Object][object Object]'
Run Code Online (Sandbox Code Playgroud)

函数或方法的参数也总是被解析为表达式:

console.log({} + {})//output: [object Object][object Object]
Run Code Online (Sandbox Code Playgroud)

在前面的解释之后,您不应该对以下结果感到惊讶:

{} + []//output: 0
Run Code Online (Sandbox Code Playgroud)

同样,这被解释为后面的代码块+[].以下表达式是等效的:

+[]
Number([])
Number([].toString())  // [].valueOf() isn’t primitive
Number("")
0
Run Code Online (Sandbox Code Playgroud)

有趣的是,Node.js REPL以不同于Firefox或Chrome的方式解析其输入(甚至使用与Node.js相同的V8 JavaScript引擎).以下输入被解析为表达式,结果不那么令人惊讶:

{} + {}//output: '[object Object][object Object]'
{} + []//output '[object Object]'
Run Code Online (Sandbox Code Playgroud)

这样做的好处是更像是将输入用作console.log()的参数时得到的结果.但它也不像在程序中使用输入作为语句.

参考

JavaScript中的{} + {}是什么?