当我在玩javascript时,发现了以下控制台输出:
[] + []
// 输出: ""[] + {}
// 输出: [object Object]{} + []
// 输出: 0{} + {}
// 输出: NaN
请问有人能解释一下这些输出背后的逻辑吗?我觉得这是一个非常奇怪的行为,但我猜可能它背后有一些逻辑。
提前感谢。
当我在玩javascript时,发现了以下控制台输出:
[] + []
// 输出: ""[] + {}
// 输出: [object Object]{} + []
// 输出: 0{} + {}
// 输出: NaN
请问有人能解释一下这些输出背后的逻辑吗?我觉得这是一个非常奇怪的行为,但我猜可能它背后有一些逻辑。
提前感谢。
期望的结果
当你在添加两个数组时,一切都按照预期工作:
[] + []//output''
[]
转换为原始类型时,首先尝试使用valueOf()
方法,该方法返回数组本身(this
):var arr = [];
arr.valueOf() === arr
true
[] + []
的结果是两个空字符串的拼接。{} + [] // output: 0
[] + {}//output '[object Object]'
String({})//output: '[object Object]'
""
和"[object Object]"
创建的。{} + {}//output: NaN
{}
解释为一个空代码块并忽略它。因此,NaN
通过计算+{}
(加号后跟第二个{}
)来计算。你在这里看到的加号不是二进制加法运算符,而是一元前缀运算符,它将其操作数转换为数字,与Number()
的方式相同。例如:+"3.65"
3.65
+{}
Number({})
Number({}.toString()) // {}.valueOf() isn’t primitive
Number("[object Object]")
NaN
{}
被解释为代码块?因为完整的输入被解析为语句,而在语句开头的花括号被解释为开始一个代码块。因此,您可以通过强制将输入解析为表达式来修复问题:({} + {})//output: '[object Object][object Object]'
console.log({} + {})//output: [object Object][object Object]
在之前的解释之后,你不应该再对以下结果感到惊讶:
{} + []//output: 0
再次强调,这被解释为一个代码块,后面跟着+[]
。以下表达式是等价的:
+[]
Number([])
Number([].toString()) // [].valueOf() isn’t primitive
Number("")
0
有趣的是,Node.js REPL在解析输入时与Firefox或Chrome不同(即使Chrome使用与Node.js相同的V8 JavaScript引擎)。以下输入被解析为表达式,结果并不令人惊讶:
{} + {}//output: '[object Object][object Object]'
{} + []//output '[object Object]'
{}
和[]
,因为它们不是单词。 - Barmar