Chromeコンソールで{} + {}がNaNでなくなったのはなぜですか?


144

今日、コンソールにNaN入力{}+{}してもChrome 49が出力されないことに気づきました。代わりに、文字列を出力します[object Object][object Object]

どうしてこれなの?言語は変わりましたか?


13
chromeはこの操作を加算ではなく文字列連結として扱うようになりました。なぜ、つまり、わからないのか、これが回答ではなくコメントである理由var e = {}; e.toString()です:)試してみると、私の意味がわかります
user428517

19
「言語は変わりましたか?」いいえ
フェリックスクリング

6
@FelixKling ウィル言語の変更は?...番号。:c
cat

18
たぶん、ワトマンはそれと関係があるのでしょうか?
rickster

1
@ricksterそれが私がそれを見つけた方法です。プレゼンテーションのためにそれを作り直していました。
Filip Haglund、2016

回答:


152

Chrome devtools は、暗黙の括弧のペア(コードを参照)で開始{および終了するすべてを自動的にラップして、その評価を式として強制します。そのようにして、空のオブジェクトを作成します。これを見るには、履歴()をさかのぼると、前の行がに含まれます。}{}(…)

どうして?わかりませんが、block-vs-object-literalを知らない初心者の混乱を減らすことができると思います。また、式を評価したいだけの場合にも役立ちます。

バグ499864で説明されているように、実際にはそれが理由です。純粋な便利さ。また、ノードREPLにもそれがあったため(コードを参照)。


182
愚かなChromeは{a:1}),({b:2}、オブジェクトを生成するのではなく、エラーをスローするべきです。
Oriol

29
これは、正規表現で任意に深くネストされた構造を解析すると何が起こるかです。stackoverflow.com
questions/1732348/

4
理由はわかりませんが、メッセージが表示されると、「有名」な気がしますが、そのページは、このページと同じように公開されています:D奇妙なStackOverflowの問題。ここで問題についての私の古い答えだstackoverflow.com/questions/17268468/...
ベンジャミンGruenbaum

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
この答えは正しいです。しかし、すごい、私はそのクロムがそれをするのが好きかどうかわかりません。悪いグーグル。
user428517

1
@sgrovesこれがCanaryでも同じであるかどうか、そしてそれが故意に行われたのか、それとも実際にバグなのかを知りたいと思います。
J. Titus

8
{} + {}に「サニタイズ」されていない場合は、が空のブロックとして解析されるため({} + {})、として扱われます。+ {}{}
Gregory Nisbet

7
そもそもなぜNaNを返すのでしょうか?
0x499602D2

25
@ 0x499602D2:かっこを使用しない限り(または、パーサーをステートメントではなく式を期待するようにシフトさせない限り)、イニシャル{}は空のコードブロックであり無視さ+{}れるため、単項+で空のオブジェクトであるが残ります初期化子。+オブジェクトをプリミティブに変換することを含む(toStringこの場合、最終的にはになり、結果としてが発生します"[object Object]")ために、その引数を数値に強制します。そのため、有効な数値に変換できないため、+"[object Object]"これが得られます。NaN"[object Object]"
TJクラウダー2016

4

コンソールに関するChrome 54以降:

📎-「そのブロックをオブジェクトに変換しました」-Clippy 残念ながら、自分でClippyの引用を追加しました。コンソールはあなたのために何をしたかについての情報を提供しません。

新しいルールは信じられないほどシンプルで、これらの2つの難しい文字を手間で入力する手間を省いo=たり0,、オブジェクトリテラルをコンソールに貼り付ける前に保存したりできます。

  • 次で始まるコードがある場合:オプションの空白(コメントは許可されません)の後に{;
  • そのコードはオブジェクトとして解釈できます。
  • 次の場合を除き、そのオブジェクトの後に他のコードは続きません。
  • 最初のオブジェクトの後のコードは2項演算子です。
  • グループ化を含め、好きなだけ操作を行うことができます
  • 最後の演算子の右側にオブジェクトリテラルがある場合。
  • そしてその最後のオブジェクトは括弧でグループ化されていません
  • そしてそのコードはセミコロンで終了していません
  • コードに続くコメントはありません(最初または最後の位置にない限り、内部コメントは許可されます)
  • そのときのみ、JavaScript(実際には有効なコードである場合とそうでない場合がある)が有効なオブジェクトとして再挿入されます。コードが再解釈されたことは通知されません。

{wat:1}),({wat:2} ようやく再びエラーです。

{let i=0;var increment=_=>i++} 最後に、正しく許可されています。これは、クロージャーを行う非常に良い方法です。

ただし、以下は誤ってオブジェクトです。これは、@ Bergiによって言及されたのと同じくらい便利です。JSが間違っていると解釈して、あなたを助けます!仕様によると、これは、何にも割り当てられていないリテラル1を含むラベル付きステートメント「foo」を含むブロックです。

{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]

次のものは、式の位置に打ち込まれたオブジェクトとして正しく解釈されます。0,これは、通常、ステートメントの代わりに式があることを明確に保証する方法です。

0,{foo:1}.foo

なぜ値が括弧で囲まれているのかわかりません。JSにはばかげた設計上の決定がありますが、この1つの状況でより適切に動作させることは実際にはオプションではなく、コンソールはJSを正しく実行する必要があります。本当に何か他のことをすることを意味しました。

コンマ演算子が気に入らない場合は、代入を使用できます

x = {foo:1}.foo

現状のまま

{} + {} + {}

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

;{} + {} + {}

"NaN[object Object]"

クレイジーで一貫性のある私は対処できます...クレイジーで一貫性がありませんありがとうございます!


REPLはREPLである言語ではありません。それは言語に文字列を渡すとりわけここでは、Chrome REPLが言語自体では行わないことをいくつか説明します。それらはかなり有用なので、私が彼らが平易な言葉だけにこだわらなかったことを本当に嬉しく思います。
gman

@gman A REPL文字列を読み取り、評価し、結果を出力してから、次の動的コードを読み取る準備をします。リンクされたページの何も無効なJavaScriptでした。コンソールコンテキストをスコープとする "$ _"変数は、REPLでのみ意味のある便利な機能であることは明らかです。それにもかかわらず、「$ _」は有効な変数名であり、残りは通常のJavaScriptで呼び出される通常の関数とクラスにすぎません。
ジェームズウェイクフィールド

あなたのポイントが何であるかわからない。私のポイントは、言語は1つのことであり、それが実行される環境は別のものです。答えの例を挙げました。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の代わりにオブジェクトとして解釈されたという警告が表示されれば嬉しく思います。
ジェームズウェイクフィールド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.