【问题标题】:Why does "[] + {} === {} + []" evaluate to "true"? [duplicate]为什么“[] + {} === {} + []” 评估为“真”? [复制]
【发布时间】:2017-04-28 16:48:13
【问题描述】:

如果你打开你的 JS 控制台并输入 [] + {} === {} + [] 它告诉你这是真的。

我不明白这是为什么。我试图查看它是如何解析的。

对于[] + {} + 这里是加法运算符,因为操作数都是文字。 LHS 不会通过.valueOf() 产生数字,因此它在两个操作数上使用.toString() 执行字符串连接,从而得到"" + "[object Object]"

对于{} + []{} 是一个空代码块并被“忽略”,这里的+ 运算符被解析为一元加运算符,它将其操作数转换为数字。转换为数字的空数组变为0

所以这似乎是"[object Object]" === 0,这肯定应该是假的?

身份运算符检查两个操作数是否相等而不进行类型转换。我看不出这怎么可能是真的。我错过了故事的哪一部分?

编辑:

我知道如果你输入 ({} + []) 它会将其解析为一个空对象,从而使 RHS 等于“[object Object]”。我查了一下,( ) 是分组运算符。那么也许这与此有关?

这不是What is the explanation for these bizarre JavaScript behaviours mentioned in the 'Wat' talk for CodeMash 2012? 的副本。回答要点 1 === 2 不应该是真的。

【问题讨论】:

  • {} 不可能被解释为一个空块,因为它紧跟在=== 之后(并且[] + {} === 本身不是一个有效的语句)。
  • 不是真正的WTF,只是对解释器的误解! :)
  • ([] + {}) === ({} + []) 也是如此
  • 这是“不重复”的第 2 点。它准确地解释了发生了什么[] + {} 评估为"[object Object]" - 字符串,然后{} + [] 做了完全相同的事情。它看起来像另一个问题中的第 3 点这一事实是无关紧要的,因为那里的驱动力是 {} 是线上的 first 事物 - 这使它成为一个空块。在这种情况下,它完全等同于{} + [],因为它产生"[object Object]"

标签: javascript


【解决方案1】:

第二点in this magnificent answer 解释了当你将一个数组和一个对象“相加”时会发生什么。

var result = [] + {};

console.log(result);
console.log(typeof result);

你得到的是 string [object Object],因为每个参数都被转换成一个字符串。对于一个数组,这会导致在其上调用.join(),这反过来又会导致一个空字符串。对于对象,它会生成字符串 "[object Object]" - 将它们加在一起会留下第二个字符串。

比较的两边也会发生同样的情况 - 在右侧,顺序不同,但这并不重要。结果将与答案中的第 3 点相同,因为不同之处在于 {} + [] 位于行首,因此 {} 被解释为空块。在这种情况下,它将(正确地)被解释为普通对象表示法)。将执行相同的转换逻辑,并生成与以前相同的字符串:"[object Object]"

所以,最后,您将比较返回 true"[object Object]" === "[object Object]"

请注意,{} + [] === [] + {}不会产生相同的结果 - 再次,由于链接答案的第 3 点 - 第一个 {} 将被解释为空块,因此左侧变为+[],它将数组转换为数字,因此比较的结果将是false然而如果你在 Chrome 开发工具中测试这个表达式,你确实会得到true。这是因为 Chrome will auto-wrap your expression in parentheses 强制将初始 {} 解释为对象。在 Firefox 或 Node REPL 或其他中检查 {} + [] === [] + {} 应该会产生“正确的”false

【讨论】:

  • 我无法弄清楚这个的格式。但是,Node 说你错了。 > {} + [] 0 > [] + {} '[object Object]' > {} + [] === [] + {} true >
  • @EricBlade 嗯,很有趣。我无法复制它,但它可能与 NodeJS 安装有关。当我写那个答案时,这肯定是它的工作原理,因为我现在没有安装它,所以我使用了运行 v9.7.1 的this online REPL service,并且确实为{} + [] === [] + {} 返回了false。我不确定您为什么会得到不同的结果,但可能是您的安装正在执行 Chrome“技巧”并实际评估 ({} + [] === [] + {}) - 可能是它的设置或最新版本的新功能。
【解决方案2】:

    var array = ['test1', 'test2', 'test3']
    var emptyObject = {}

    console.log(typeof(array+emptyObject));
    console.log(array+emptyObject);
    console.log(emptyObject+array);
    console.log(array+emptyObject === emptyObject+array);

    var array = [];
    var emptyObject = {}

    console.log(typeof(array+emptyObject));
    console.log(array+emptyObject);
    console.log(emptyObject+array);
    console.log(array+emptyObject === emptyObject+array);

    var array = ['firstArrayElement', 'secondArrayElement'];
    var object = {a:1, b:2}
    
    console.log(typeof(array+object));
    console.log(array+object);
    console.log(object+array);
    console.log(array+object === object+array);

    console.log(['a','b']+['c','d']);

当您将空数组转换为字符串时,您将收到空字符串。

当您将对象({})转换为字符串时,您将始终收到字符串:“[object Object]”。

没有为数组和对象定义加号运算符,所以当你使用加号运算符时,JS总是将数组和对象转换为字符串。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-22
    • 2014-05-19
    • 2014-02-16
    • 1970-01-01
    • 2018-07-01
    • 2020-04-03
    • 2023-03-20
    • 2017-12-21
    相关资源
    最近更新 更多