JavaScript中的{}-0 VS ({}-0)是什么意思?

17
在Chrome JavaScript控制台中,为什么用括号包裹语句 {} - 0 可以改变返回值?
{} - 0    // Returns -0
({} - 0)  // Returns NaN

把一个语句用括号括起来就能改变其值,这看起来非常奇怪。我错过了什么吗?


好问题,当然有比我更有知识的人。我猜这可能与你将它包裹在括号中有关,这使它成为一个自执行函数? - jdmdevdotnet
2
https://www.destroyallsoftware.com/talks/wat - Joe Hawkins
1
视为空块,与空对象 - epascarello
1
@JoeHawkins 嘿,我之前看过WAT演讲。它实际上激发了我去尝试一些奇怪的表达式。 - Elliot Godzich
一方面,我想要点赞这个...另一方面,我想将其投票到遗忘之地... - user541686
3个回答

19

这行代码{} - 0有两种可能的解释:

  1. 可以被解释为{}; -0,其中{}被解释为空的块语句,而-是一元否定运算符(因此-0就是“负零”)。当计算其值时,它的值是最后一条语句的值,即-0。
  2. 也可以被解释为({} - 0),其中{}被解释为空对象,而-是减法运算符(因此从{}中减去0)。

在第一行中,这是模棱两可的,所以会选择第一个解释。在第二行中,第一个解释无效(因为块语句永远不可能成为表达式的一部分,你正在强制使用括号)。


4
这是一个非常有趣的问题。虽然我不是原帖发布者,但我有一个关于这个问题的跟进:如果您添加一个方法或属性来强制将{}解释为对象会怎样呢? 这对括号有效,但没有括号无效。(例如,使用括号,此表达式计算为3({valueOf:()=>3} - 0),但是没有括号,它仍然在控制台中返回 -0: {valueOf:()=>3} - 0)。这时候,添加的方法难道不应该强制将{..}解释为对象,然后尝试进行减法运算吗? - Joseph Marikle
@JosephMarikle 我认为这里的推理仍然适用,即使没有括号,它仍然可以被解释为{valueOf:()=>3}; -0,但是({valueOf:()=>3}; -0)是语法错误。 - Elliot Godzich
6
您可能会认为是这样,但实际上不是:在这种情况下,valueOf:是一个标签语句(一种罕见的JavaScript特性),在语句() => 3;之前,因此它仍然被解释为块语句而不是对象。 它被解释为{ valueOf: () => 3; }; -0相同的方式。 - Frxstrem
2
@JosephMarikle 如果您添加多个属性,它就不能再是块语句了:{ a: 1, b: 2 }不能成为块语句,因为标签语句不能出现在逗号后面(因为它们不能成为表达式的一部分)。 - Frxstrem
1
@Frxstrem 非常有趣。感谢您的解释。有趣的是,在强制使用第二个属性/方法的对象之后,它只会抛出语法错误(至少在Chrome中)。{valueOf:()=>3,a:0} - 0 - Joseph Marikle
@JosephMarikle 是的,我注意到了。我无法准确解释为什么(我不知道JS是如何解析的细节),但是如果您对此感兴趣,这个问题似乎有一些有趣的相关答案。 - Frxstrem

4

{} - 0: 这里的 {} 只是一个什么也不做的空块,所以控制台返回了 -0

({} - 0): 这里的 {} 是表达式的一部分,并被转换为数字。在这个空对象中没有定义 valueOf() 方法,在转换为数字时,它会回退到 toString() 方法,对于 {} 返回类似于 object Object 的内容。然后,将这个字符串 object Object 转换为数字,由于它实际上不是一个数字,因此返回 NaN。因此,我们有:

({} - 1) -> ('object Object' - 1) -> (NaN - 1)

任何与 NaN 相关的操作都会返回 NaN,这就是最终在控制台中看到的结果。


2
{} - 0

被解释为:{} 空块语句- 0 负零

({} - 0)

()内的所有内容都被解释为一个表达式,空对象 - 0 = NaN


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接