Страницы

Поиск по вопросам

суббота, 30 ноября 2019 г.

{} + {}. Почему такой результат?

#javascript


{} + {}
"[object Object][object Object]"

В статье Преобразование объектов: toString и valueOf в разделе Итоги описывается
поведение объекта( {} ) в основном потоке кода, но в консоли поведение отличается.
Я даже где - то видел подобный пример: {} + {}. Там говорилось, что левый операнд считается
как пустой "блок кода", а правый приводиться к числу, результатом который будет NaN.

За одно хотел спросить, как видит парсер это пример: {} - {}.


Парсер игнорирует левый объект и воспринимает его как "блок кода". Тогда возникает
вопрос, почему в примере выше происходит конкатенация?
Он их приводит к числу(NaN) и вычитает.




P.S: Знал бы английский и умел бы хорошо понимать документация ECMAScript, я бы не
спрашивал.
    


Ответы

Ответ 1



Основной поток кода - это место, которое не является частью выражения. Вот моменты языка, которые могут быть размещены только в основном потоке кода: function declaration (отличается от function expression) блок кода (отличается от объекта) метки (отличаются от имён свойств) все синтаксические конструкции языка: if, else, try, var и т. д. Если есть две похожие конструкции, одна из которых может существовать только в основном потоке, то именно этот критерий будет использоваться для их различения: если код размещён в основном потоке кода, то выбирается соответствующая конструкция, а если в выражении, то другая. Что касается записи {}+{}, то в случае основного потока кода её значение обычно вообще никуда не попадает, хотя и выводится в REPL-средах как результат. Первая фигурная скобка означает открытие блока кода, затем вторая его заканчивает. Потом попадается плюс - левого операнда у нас нет, значит он унарный. Мы уже находимся в выражении. Фигурная скобка в выражении начинает объект. Следующая - заканчивает объект. Получается +{}, затем +"[object Object]" и NaN. В случае же с console.log сам вызов функции образует выражение. Поэтому первая пара скобок превращается в объект, а вся сумма после приведения типов в конкатенацию строк. Единственный способ (по крайней мере в ES2018-) получить в коде это передать строку с кодом в eval. function run(code) { try { console.log(eval(code)) } catch(e) { console.log(e.name + " " + e.message) } } run('{console.log("I am the code block")} + {i:0, am:1, an:2, object:3}') run('({a:0, pair:1} + {of:2, objects:3})') // круглые скобки run('{not_object:0} + {object:1}') // метка! run('{not_object:0, really_not:1} + {object:2}') // ошибка - метка не может быть вне основного потока run('{not_object:0; really_not:1} + {object:1}') // `;`, а не `,` - две метки Что касается консоли хрома - судя по всему они сделали умное определение, является ли нечто в фигурных скобках объектом или куском кода. Причём, предпочтение отдаётся объекту. Думаю, это сделано для большего удобства, что если ты вводишь выражение в консоль, то ты хочешь результат выражения, который ты не получишь в основном потоке кода. Но стоит заметить, что эта штука в консоли работает только для top-level-кода (да и то не всегда), и не распространяется на вложенный код:

Ответ 2



Приведение. Если может к числам приводит к числам. Если не может то приводит к строке, {} + {}, вызывает приведение к строке, конкатенация 2-х строк. При вычитании считается что оба операнда числа, преобразование не происходит возвращается NaN

Комментариев нет:

Отправить комментарий