为什么{} + {}在Chrome控制台中不再为NaN?


144

我今天注意到,NaN当您输入{}+{}控制台时,Chrome 49不再输出。而是输出字符串[object Object][object Object]

为什么是这样?语言改变了吗?


13
看起来chrome现在将此操作视为字符串concat而不是加法。为什么,我不知道,这就是为什么这是评论而不是答案:)尝试var e = {}; e.toString(),您将明白我的意思
user428517

19
“语言改变了吗?”
Felix Kling

6
@FelixKling 语言的变化?...没有。:c
cat

18
也许WATMAN与它有关?
rickster '16

1
@rickster这就是我发现它的方式。我正在重新创建演示文稿。
Filip Haglund

Answers:


152

现在,Chrome devtools会自动在隐含的一对括号(请参阅代码)中包装所有以开头{和结尾的内容,以强制将其评估为表达式。这样,现在创建一个空对象。如果您回顾历史记录(),则会看到此内容,前一行将包含在中。}{}(…)

为什么?我不知道,但是我可以猜到它可以减少对于不了解block-vs-object-literal的新手的困惑,如果您只想评估一个表达式,它也将更加有用。

实际上,这就是原因,如错误499864中所述。纯粹的便利。而且因为节点REPL也具有它请参见代码)。


182
愚蠢的Chrome,{a:1}),({b:2}应该抛出错误,而不产生对象。
Oriol


4
我不知道为什么,但是以某种方式看到那里的消息时,我感到“着名”,尽管该页面与这个:D Weird StackOverflow问题一样公开。这是我对问题stackoverflow.com/questions/17268468/…的
Benjamin Gruenbaum 2016年

3
我不喜欢当前的实现,并计划对其进行修复。bugs.chromium.org/p/chromium/issues/detail?id=499864#c17
Zirak,

1
@Zirak祝你好运,修复垃圾,IMO应该尽快取消。但是,如果要改进它,请考虑在插入之前添加换行符),以防它出现在注释中,例如,{a:3} // :-}可能仍会产生一个对象。
Oriol

44

如果您选中此之后击中向上箭头,你会发现,而不是{} + {}它的显示器({} + {}),其结果"[object Object][object Object]"

相比之下,在Firefox中,{} + {}仍会显示NaN,但是如果您这样做({} + {}),也会显示"[object Object][object Object]"

因此,当Chrome浏览器看到此操作时,它似乎会自动添加周围的括号。


22
这个答案是正确的。但是,哇,伙计,我不确定我是否喜欢Chrome那样做。不好的谷歌。
user428517 '16

1
@sgroves我很想看看这在Canary中是否相同,以及是否有意这样做或实际上是一个错误。
J. Titus

8
{} + {}当未“清理”为时,将({} + {})被视为+ {}因为{}被解析为空块。
Gregory Nisbet

7
为什么首先返回NaN?
0x499602D2'6

25
@ 0x499602D2:因为除非您进行了解析(否则使解析器转变为期望表达式而不是语句),否则首字母{}只是一个空的代码块而被忽略,留下给我们+{},这是一个一元+且空的对象初始化程序。+会将其参数强制转换为number,这涉及将对象转换为原语(toString在这种情况下最终将是a ,导致"[object Object]"),因此我们得到了+"[object Object]"这是NaN因为"[object Object]"无法将其转换为有效数字。
TJ Crowder

4

从Chrome 54开始,关于控制台:

📎-“我已为您将块转换为对象” -Clippy 不幸的是,我自己添加了Clippy报价。控制台不提供有关为您完成的操作的信息。

新规则非常简单,为我们省去了繁琐地键入这两个困难字符o=0,在将对象文字粘贴到控制台之前的麻烦:

  • 如果您的代码开头为:可选的空格,(不允许输入任何注释),后跟一个 {
  • 该代码可以解释为一个对象;
  • 并且该对象后面没有其他代码,除非:
  • 第一个对象之后的代码是二进制运算符,
  • 那么您可以根据需要进行任意操作,包括分组
  • 如果最终运算符在右侧位置具有Object文字;
  • 并且该最终对象尚未在括号中分组
  • 并且该代码不以分号终止
  • 并且代码后没有注释(内部注释是允许的,只要它们不在初始位置或最终位置即可)
  • 然后,只有这样,您的JavaScript(实际上可能是无效代码)才能重新输入为有效对象。您不会被告知您的代码已被重新​​解释。

{wat:1}),({wat:2} 终于又是一个错误。

{let i=0;var increment=_=>i++} 最后,正确地允许它,这是进行关闭的一种不错的方法。

但是,以下对象错误地是一个对象,正如@Bergi所提到的那样,这是一种方便,它会错误地解释JS来帮助您!规范说这是一个带有标记语句“ foo”的块,其文字为1,未分配任何内容。

{foo:1}

以上应与

if(1) {
    foo: 1
}

以下内容被正确地视为一个块...因为它前面有注释!

//magic comment
{foo:1}

这是这样的:

{foo:1}
//also magic

这是一个对象:

{foo:
//not so magic comment
1}

这是一个错误

//not so magic comment
{foo:1}.foo

这是这样的:

{foo:1}.foo

这可以:

1..wat

undefined

是这样的:

['foo'][0]

下一个正确地解释为一个对象,用a冲进了表达式位置,0,这通常是我们明确地确保我们拥有表达式而不是语句的方式。

0,{foo:1}.foo

我不明白他们为什么将这些值包装在括号中。JS做出了一些荒谬的设计决策,但要使它在这种情况下表现得更好并不是真正的选择,控制台需要正确运行JS,我们需要确信chrome并不仅仅是在猜测它认为我们真的意味着要做其他事情。

如果您不喜欢逗号运算符,则可以使用赋值

x = {foo:1}.foo

因为目前

{} + {} + {}

"[object Object][object Object][object Object]"

;{} + {} + {}

"NaN[object Object]"

疯狂而始终如一的我可以应付……疯狂而又自相矛盾的不,谢谢!


REPL不是语言,而是REPL。它将字符串传递给语言等等Chrome REPL会做几种语言本身没有做的事情。它们非常有用,所以我很高兴他们不仅仅坚持简单的语言。
gman

@gman REPL读取一个字符串,对其求值,打印结果,然后准备读取下一段动态代码。链接页面中没有任何内容是无效的JavaScript。范围仅限于控制台上下文的“ $ _”变量显然是一种便利,仅在REPL中才有意义。但是,“ $ _”是有效的变量名,其余的只是普通的函数和使用普通JavaScript调用的类。
James Wakefield

不知道你的意思是。我的观点是语言是一回事,它所运行的环境是另一回事。您在答案中举了一个例子。在JS {foo:1}{foo:1}//生产同样的事情。在Chrome JS REPL中却没有。REPL所做的不仅仅是评估JS。它正在处理字符串并决定使用不同的东西。
gman

var x = eval('{a:1}')在有效的JavaScript中,x现在为1,而不是更直观的对象{a:1}。是的,这很奇怪,但是您不能只更改语言,因为它确实很奇怪。除JSON字符串外,其他所有内容都将解释为JavaScript并进行评估。0,在粘贴JSON之前进行键入并不难,或者为方便起见,我对警告将字符串解释为对象而不是JavaScript感到满意。
詹姆斯·韦克菲尔德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.