在javascript中添加两个空白对象或空白数组
我正在玩javascript时发现了以下控制台输出:在javascript中添加两个空白对象或空白数组,javascript,type-conversion,Javascript,Type Conversion,我正在玩javascript时发现了以下控制台输出: []+[]//输出:“ []+{}//输出:[对象] {}+[]//输出:0 {}+{}//输出:NaN 谁能给我解释一下这些输出背后的逻辑。我觉得这是一种非常奇怪的行为,但我想可能有一些逻辑 提前感谢。预期结果 添加两个阵列时,一切正常: [] + []//output'' 将[]转换为原语首先尝试valueOf(),返回数组本身(this): 由于该结果不是原语,接下来调用toString()并返回空字符串(原语)。因此,[]+[]的结
[]+[]
//输出:“[]+{}
//输出:[对象]{}+[]
//输出:0{}+{}
//输出:NaN提前感谢。预期结果 添加两个阵列时,一切正常:
[] + []//output''
将[]
转换为原语首先尝试valueOf()
,返回数组本身(this
):
由于该结果不是原语,接下来调用toString()并返回空字符串(原语)。因此,[]+[]
的结果是两个空字符串的串联
{} + [] // output: 0
添加数组和对象也符合我们的期望:
[] + {}//output '[object Object]'
说明:将空对象转换为字符串将产生以下结果
String({})//output: '[object Object]'
因此,前面的结果是通过连接“
和”[object object]“
创建的
意外结果
如果+的第一个操作数是空的对象文字(结果如Firefox控制台上所示),事情就会变得奇怪:
这是怎么回事?问题是JavaScript将第一个{}
解释为空代码块并忽略它。因此,通过计算+{}
(加上第二个{}
)来计算NaN
。这里看到的加号不是二进制加法运算符,而是一元前缀运算符,它将操作数转换为数字,方式与number()
相同。例如:
+"3.65"
3.65
以下表达式都是等效的:
+{}
Number({})
Number({}.toString()) // {}.valueOf() isn’t primitive
Number("[object Object]")
NaN
+[]
Number([])
Number([].toString()) // [].valueOf() isn’t primitive
Number("")
0
为什么第一个{}
被解释为代码块?因为完整的输入被解析为语句,而语句开头的大括号被解释为启动代码块。因此,您可以通过强制将输入解析为表达式来解决问题:
({} + {})//output: '[object Object][object Object]'
函数或方法的参数也始终解析为表达式:
console.log({} + {})//output: [object Object][object Object]
在前面的解释之后,您不应该再对以下结果感到惊讶:
{} + []//output: 0
同样,这被解释为一个代码块,后跟+[]
。以下表达式是等效的:
+{}
Number({})
Number({}.toString()) // {}.valueOf() isn’t primitive
Number("[object Object]")
NaN
+[]
Number([])
Number([].toString()) // [].valueOf() isn’t primitive
Number("")
0
有趣的是,Node.js REPL解析其输入的方式不同于Firefox或Chrome(后者甚至使用与Node.js相同的V8 JavaScript引擎)。以下输入被解析为表达式,结果就不那么令人惊讶了:
{} + {}//output: '[object Object][object Object]'
{} + []//output '[object Object]'
这样做的好处是更像将输入用作console.log()的参数时得到的结果。但它也不像在程序中使用输入作为语句
参考资料
唉,我知道以前有人问过这个问题,但SO不允许您搜索
{}
和[]
,因为它们不是单词。