Чому {} + {} більше не працює NaN у консолі Chrome?


144

Сьогодні я помітив, що Chrome 49 більше не виводиться NaNпід час введення {}+{}в консоль. Натомість він виводить рядок [object Object][object Object].

Чому це? Чи змінилася мова?


13
схоже, що хром зараз трактує цю операцію як стислий стринг, а не як доповнення. ЧОМУ це, я не знаю, саме тому це коментар, а не відповідь :) спробуйте, var e = {}; e.toString()і ви побачите, що я маю на увазі
user428517

19
"Чи змінилася мова?"
Фелікс Клінг

6
@FelixKling Чи зміниться мова? ...немає. : c
кішка

18
Може бути, WATMAN щось із цим пов’язав ?
рикстер

1
@rickster ось так я це знайшов. Я відтворював це для презентації.
Філіп Хаглунд

Відповіді:


152

Тепер розробники Chrome автоматично загортають все, що починається {і закінчується, }в неявну пару дужок ( див. Код ), щоб змусити його оцінювати як вираз. Таким чином, {}створює порожній об’єкт зараз. Це можна побачити, якщо ви повернетесь до історії ( ), попередній рядок міститиметься в (…).

Чому? Я не знаю, але я можу здогадатися, що це зменшує плутанину для новачків, які не знають про буквальний предмет блок-vs-об’єкт-буквально, а також корисніше, якщо ви просто хочете оцінити вираз.

Насправді це міркування, про які йдеться у помилці 499864 . Чиста зручність. А тому, що у вузла REPL його було також ( див. Код ).


182
Дурний Chrome, {a:1}),({b:2}повинен кидати помилку, а не створювати об'єкт.
Оріол

29
Ось що відбувається, коли ви аналізуєте довільно глибокі вкладені структури з регулярним виразом stackoverflow.com/questions/1732348/…
Філіп Хаглунд

4
Я поняття не маю, чому, але якось, коли я бачу там свої повідомлення, я відчуваю себе "відомим", хоча ця сторінка настільки ж публічна, як ця: D Weird StackOverflow. Ось моя старша відповідь про проблему stackoverflow.com/questions/17268468/…
Бенджамін Грюнбаум

3
Мені не подобається поточна реалізація і планую її виправити. bugs.chromium.org/p/chromium/issues/detail?id=499864#c17
Zirak

1
@Zirak Удачі, виправляючи це сміття, IMO його слід якнайшвидше підкріпити. Але якщо ви хочете вдосконалити його, подумайте про додавання нового рядка до вставленого )у випадку, якщо він є в коментарі, наприклад, {a:3} // :-}можливо, все-таки створюється об’єкт.
Оріол

44

Якщо натиснути стрілку вгору після перевірки, ви помітите, що замість {} + {}неї відображається ({} + {}), що призводить до "[object Object][object Object]".

Для порівняння, у Firefox {} + {}все ще відображається NaN, але якщо ви ({} + {})це зробите, він також відображається "[object Object][object Object]".

Отже, схоже, Chrome автоматично додає навколишні дужки, коли бачить цю операцію.


22
ця відповідь правильна. але вау, чоловіче, я не впевнений, що мені подобається, що хром це робить. поганий google.
user428517

1
@sgroves Мені було б цікаво дізнатися, чи це те саме в Canary, і чи це було зроблено навмисно чи насправді помилка.
Дж. Тит

8
{} + {}коли не "санітована" до ({} + {}), трактується як + {}тому {}, що аналізується як порожній блок.
Григорій Нісбет

7
Чому б повернути NaN в першу чергу?
0x499602D2

25
@ 0x499602D2: Оскільки, якщо ви не зробите паролі (або іншим чином не змусите парсера перейти на очікування виразу, а не на заяву), початковий {}код є лише порожнім кодом блоку і не враховується, залишаючи нас +{}, що є унарним +і порожнім об'єктом ініціалізатор. +буде примушувати свій аргумент до числа, що включає перетворення об'єкта в примітив (що в кінцевому підсумку toStringв цьому випадку буде результатом "[object Object]"), і таким чином ми отримаємо +"[object Object]"це, NaNтому що "[object Object]"не може бути перетворене на дійсне число.
TJ Crowder

4

Що стосується Chrome 54 щодо консолі:

📎- "Я перетворив цей блок в" Об'єкт для вас "-Clippy На жаль, я сам додав цитату Clippy. Консоль не дає інформації про те, що вона зробила для вас.

Нові правила неймовірно прості, рятуючи нас від клопоту, щоб наполегливо набрати ці 2 складні графіки o=або 0,перед тим, як вставити Об'єктні літерали в консоль:

  • Якщо у вас є код , який починається з: необов'язкового пропуску, (немає коментарів дозволено) , а потім {;
  • і цей код можна інтерпретувати як об'єкт;
  • і цей об'єкт не супроводжується жодним іншим кодом, якщо:
  • код після першого об'єкта є двійковим оператором,
  • тоді може бути стільки операцій, скільки вам подобається, включаючи групування
  • за умови, що кінцевий оператор має літеру «Об’єкт» у положенні правої руки;
  • і цей кінцевий Об'єкт не згруповано в паренах
  • і цей код не закінчується крапкою з комою
  • і за кодом немає коментарів (внутрішні коментарі дозволені до тих пір, поки вони не перебувають у початковій чи кінцевій позиції)
  • тоді і лише тоді ваш 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]

Наступний правильно інтерпретується як об'єкт, що потрапив у позицію вираження, а 0,це, як правило, те, як ми однозначно гарантуємо, що замість висловлювання є вираз.

0,{foo:1}.foo

Я не розумію, чому вони обертають цінність у паронах. JS має кілька смішних дизайнерських рішень, але намагатися змусити себе вести себе приємніше в цій одній ситуації - це насправді не варіант, консолі потрібно запустити JS правильно, і ми повинні бути впевнені, що хром не просто здогадується, що він думає, що ми думаємо насправді означало це зробити щось інше.

Якщо вам не подобаються оператори з комами, ви можете використовувати призначення

x = {foo:1}.foo

Бо як стоїть

{} + {} + {}

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

;{} + {} + {}

"NaN[object Object]"

Божевільний і послідовний, з яким я можу мати справу ... божевільний і непослідовний, не дякую!


a REPL - це не мова, що це REPL. Він передає рядки мові серед іншого . Ось декілька речей, якими Chrome REPL займається мовою, якої вона не робить . Вони дуже корисні, тому я дуже радий, що вони не дотримувались простої мови.
gman

@gman A REPL Читає рядок, оцінює її, друкує результати і потім готується прочитати наступний фрагмент динамічного коду. Нічого на пов’язаній сторінці не було вказано неправильним JavaScript. Змінна "$ _", яка охоплюється контекстом консолі, очевидно, є зручністю, яка має сенс лише у системі REPL. Тим не менш, "$ _" - допустиме ім'я змінної, решта - це лише звичайні функції та класи, на які посилається звичайний JavaScript.
Джеймс Уейкфілд

Не впевнений, у чому полягає ваша суть. Моя думка - мова - це одне, оточення, в яке вона працює, - інше. Ви подали приклад у своїй відповіді. У 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 для зручності.
Джеймс Уейкфілд
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.