Mengapa {} + {} tidak lagi NaN di konsol Chrome?

144

Saya perhatikan hari ini bahwa Chrome 49 tidak lagi menghasilkan NaNketika Anda mengetik {}+{}ke konsol. Sebaliknya itu menghasilkan string [object Object][object Object].

Kenapa ini? Apakah bahasanya berubah?

Filip Haglund
sumber
13
Sepertinya chrome sekarang memperlakukan operasi ini sebagai string string daripada penambahan. MENGAPA itu, saya tidak tahu, itulah sebabnya ini adalah komentar bukan jawaban :) coba var e = {}; e.toString()dan Anda akan melihat apa yang saya maksud
user428517
19
"Apakah bahasanya berubah?" Tidak.
Felix Kling
6
@FelixKling Akankah bahasa berubah? ...tidak. : c
cat
18
Mungkin WATMAN ada hubungannya dengan itu?
rickster
1
@ penipu itulah bagaimana saya menemukannya. Saya sedang menciptakan itu untuk presentasi.
Filip Haglund

Jawaban:

152

Chrome devtools sekarang secara otomatis membungkus segala sesuatu yang dimulai dengan {dan diakhiri dengan }sepasang kurung implisit ( lihat kode ), untuk memaksa evaluasinya sebagai sebuah ekspresi. Dengan begitu, {}buat objek kosong sekarang. Anda dapat melihat ini jika Anda kembali melalui histori ( ), baris sebelumnya akan terkandung dalam (…).

Mengapa? Saya tidak tahu, tapi saya bisa menebak itu mengurangi kebingungan untuk pemula yang tidak tahu tentang hal block-vs-object-literal, dan itu juga lebih membantu jika Anda hanya ingin mengevaluasi ekspresi.

Dan sebenarnya itulah alasannya, seperti yang dibahas dalam bug 499864 . Kenyamanan murni. Dan karena simpul REPL memilikinya juga ( lihat kode ).

Bergi
sumber
182
Chrome bodoh, {a:1}),({b:2}harus melempar kesalahan, tidak menghasilkan objek.
Oriol
29
Itulah yang terjadi ketika Anda mem-parsing struktur bersarang dalam-dalam dengan regex stackoverflow.com/questions/1732348/...
Filip Haglund
4
Saya tidak tahu mengapa, tetapi ketika saya melihat pesan-pesan saya di sana, saya merasa "terkenal" walaupun halaman itu sama publiknya dengan yang ini: D Weird StackOverflow problem. Inilah jawaban saya yang lebih lama tentang masalah stackoverflow.com/questions/17268468/...
Benjamin Gruenbaum
3
Saya tidak suka implementasi saat ini dan berencana untuk memperbaikinya. bugs.chromium.org/p/chromium/issues/detail?id=499864#c17
Zirak
1
@Zirak Semoga berhasil memperbaiki sampah itu, IMO itu harus didukung secepatnya. Tetapi jika Anda ingin memperbaikinya, pertimbangkan untuk menambahkan baris baru sebelum dimasukkan )jika ada dalam komentar, misalnya {a:3} // :-}mungkin masih menghasilkan objek.
Oriol
44

Jika Anda menekan panah ke atas setelah memeriksa ini, Anda akan melihat bahwa alih-alih {} + {}itu ditampilkan ({} + {}), yang menghasilkan "[object Object][object Object]".

Sebagai perbandingan, di Firefox, {} + {}masih menampilkan NaN, tetapi jika Anda melakukannya ({} + {})juga menampilkan "[object Object][object Object]".

Jadi, sepertinya Chrome menambahkan tanda kurung di sekitarnya secara otomatis ketika melihat operasi ini.

J. Titus
sumber
22
jawaban ini benar. tapi wow, kawan, saya tidak yakin saya suka krom yang melakukan itu. google buruk
user428517
1
@sgroves Saya akan tertarik untuk melihat apakah ini sama di Canary, dan apakah itu dilakukan dengan sengaja atau sebenarnya adalah bug.
J. Titus
8
{} + {}ketika tidak "disanitasi" untuk ({} + {})diperlakukan sebagai + {}karena {}diurai sebagai blok kosong.
Gregory Nisbet
7
Mengapa itu mengembalikan NaN?
0x499602D2
25
@ 0x499602D2: Karena kecuali Anda melakukan parens (atau menyebabkan parser beralih ke mengharapkan ekspresi daripada pernyataan), inisial {}hanya blok kode kosong dan diabaikan, meninggalkan kita dengan +{}, yang merupakan objek unary +dan kosong penginisialisasi. +akan memaksa argumennya ke angka, yang melibatkan konversi objek ke primitif (yang akhirnya akan menjadi toStringdalam kasus ini, menghasilkan "[object Object]"), dan kami mendapatkan +"[object Object]"yang NaNkarena "[object Object]"tidak dapat dikonversi ke nomor yang valid.
TJ Crowder
4

Pada Chrome 54 berkaitan dengan konsol:

📎- "Saya mengonversi blok itu menjadi Object for you" -Clippy Sayangnya, saya menambahkan kutipan Clippy sendiri. Konsol tidak memberikan informasi tentang apa yang telah dilakukan untuk Anda.

Aturan baru ini sangat sederhana, menyelamatkan kita dari kesulitan mengetik 2 karakter sulit ini o=atau 0,sebelum menempelkan Object Literals ke konsol:

  • Jika Anda memiliki kode yang dimulai dengan: spasi kosong opsional, (tidak ada komentar yang diizinkan) diikuti oleh {;
  • dan kode itu dapat diartikan sebagai objek;
  • dan objek itu diikuti oleh tidak ada kode lain, kecuali:
  • kode setelah objek pertama adalah operator biner,
  • maka bisa ada operasi sebanyak yang Anda suka termasuk pengelompokan
  • asalkan operator akhir memiliki Objek literal di posisi kanan;
  • dan Objek akhir itu belum dikelompokkan dalam parens
  • dan kode itu tidak diakhiri dengan tanda titik koma
  • dan tidak ada komentar mengikuti kode (komentar internal diizinkan selama mereka tidak berada di posisi awal atau akhir)
  • kemudian dan hanya saat itulah JavaScript Anda (yang mungkin atau mungkin bukan kode yang benar-benar valid) akan dimasukkan kembali sebagai Obyek yang valid. Anda tidak akan diberitahu bahwa kode Anda telah ditafsirkan kembali.

{wat:1}),({wat:2} Akhirnya kesalahan lagi.

{let i=0;var increment=_=>i++} akhirnya diizinkan dengan benar, yang merupakan cara yang cukup baik untuk melakukan penutupan.

Namun, berikut ini adalah objek yang salah, ini hanya sebagai kenyamanan seperti yang disebutkan oleh @Bergi, itu menafsirkan JS salah untuk membantu Anda! Spec mengatakan itu adalah blok dengan pernyataan berlabel "foo" dengan 1 literal yang tidak ditugaskan untuk apa pun.

{foo:1}

Di atas harus sama dengan

if(1) {
    foo: 1
}

Berikut ini diperlakukan dengan benar sebagai blok ... karena memiliki komentar di depannya!

//magic comment
{foo:1}

Begitu juga ini:

{foo:1}
//also magic

Ini adalah sebuah Objek:

{foo:
//not so magic comment
1}

Ini adalah kesalahan

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

Begitu juga ini:

{foo:1}.foo

Ini baik:

1..wat

undefined

begitu juga ini:

['foo'][0]

Yang berikutnya ditafsirkan dengan benar sebagai objek yang dipukul ke posisi ekspresi dengan 0,yang umumnya bagaimana kita memastikan kita memiliki ekspresi bukannya pernyataan.

0,{foo:1}.foo

Saya tidak mengerti mengapa mereka membungkus nilai dalam parens. JS memiliki beberapa keputusan desain yang konyol, tetapi mencoba membuatnya berperilaku lebih baik dalam situasi yang satu ini sebenarnya bukan pilihan, konsol perlu menjalankan JS dengan benar, dan kita perlu yakin bahwa chrome tidak hanya menebak bahwa menurutnya kita berpikir benar-benar bermaksud melakukan sesuatu yang lain.

Jika Anda tidak menyukai operator koma, Anda dapat menggunakan penugasan

x = {foo:1}.foo

Karena sebagaimana adanya

{} + {} + {}

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

;{} + {} + {}

"NaN[object Object]"

Gila dan konsisten saya bisa berurusan dengan ... gila dan tidak konsisten tidak, terima kasih!

James Wakefield
sumber
REPL bukan bahasa itu REPL. Ini melewati string ke bahasa antara lain . Berikut beberapa hal yang Chrome REPL tidak bahasa sendiri . Mereka sangat berguna jadi saya sangat senang mereka tidak hanya menggunakan bahasa yang sederhana.
GM
@ gman A REPL Membaca string, Mengevaluasinya, Mencetak hasilnya dan kemudian bersiap untuk membaca bagian berikutnya dari kode dinamis. Tidak ada di halaman yang tertaut yang merupakan JavaScript yang tidak valid. Variabel "$ _" yang dicakup dalam konteks konsol jelas merupakan kenyamanan yang hanya masuk akal dalam REPL. Meskipun demikian, "$ _" adalah nama variabel yang valid, sisanya hanya fungsi normal dan kelas dipanggil dengan JavaScript normal.
James Wakefield
Tidak yakin apa maksud Anda. Maksud saya adalah bahasa adalah satu hal, lingkungan tempat ia bekerja adalah hal lain. Anda memberi contoh dalam jawaban Anda. Di JS {foo:1}dan {foo:1}//menghasilkan hal yang sama. Di Chrome JS REPL mereka tidak. REPL melakukan lebih dari sekadar mengevaluasi JS. Ini memproses string dan memutuskan untuk hal-hal yang berbeda.
gman
var x = eval('{a:1}')Dalam JavaScript x yang valid sekarang 1, bukan objek yang lebih intuitif {a: 1}. Ya, itu aneh, tetapi Anda tidak bisa hanya mengubah bahasa karena melakukan hal-hal aneh. Segala sesuatu selain string JSON ditafsirkan sebagai JavaScript dan dievaluasi. Mengetik 0,sebelum menempelkan JSON tidak sulit, atau saya akan senang dengan peringatan bahwa string ditafsirkan sebagai objek, bukan JavaScript untuk kenyamanan.
James Wakefield