← Back to list

JavaScript или JavaScripit?

Чем заняться в пятницу?

Yohan · 2017-08-04 10:06 · 0 claps · 1.8 min read
#javascript #ecma-262 #js-type-coercion
Open on Medium ↗
Wiki topics: 🌐 · Web Development

JavaScript или JavaScripit?

Чем заняться в пятницу?

Или как опечатка в консоли разработчика заставила лезть в исходники V8 и (gospodee) в спецификацию ecma-262.

Во что интерпретатор превратит

{}.1

Если кажется что в SyntaxError, то у вас тоже скрипит.

{}.1
// -> 0.1

¯_(ツ)_/¯

{}.1 == 0.1
// -> true

Дальше пошел кураж, а что если превратить это в старую шутку про 0.1 + 0.2 == 0.3 ?

{}.1 + {}.2 == {}.3
// -> Uncaught SyntaxError: Unexpected number

Может нужно отсыпать скобочек?

({}.1) + ({}.2) == ({}.3)
// -> Uncaught SyntaxError: Unexpected number
({}.1 + {}.2) == ({}.3)
// -> Uncaught SyntaxError: Unexpected number

После испытаний еще нескольких вариантов написания, стали закрадываться определенные вопросы. Скинув исходную дичь в чат коллегам, получил в ответ закономерный “WTF?” и несколько вариантов усугубивших дело:

{}'wtf'
// -> 'wtf'
{}['wtf']
// -> ['wtf']

И даже

{}{}{}'WTF???'
// -> 'WTF???'

Ну значит настало время читать доки, ecma-262 сам себя не прочитает.

Моим предположением было что заботливый парсер переносит Token::RBRACE в конец выражения и мы получаем вызов суперобъекта Object('wtf') , Object(123) или Object(.1) как в исходном выражении. Примитив аргумента как раз и будет тем, что получаем в консоли.

+Object(.1)
// -> 0.1
Object(['wtf'])
// -> ["wtf"]

Поиски подобного поведения при (беглом) чтении спецификации ничего не дали. Исходники V8 вообще погрузили в печаль.

Развязка

{.1} == +Object(.1)
// -> Uncaught SyntaxError: Unexpected token ==

Падажжи, братан, почему? Потому что {} помимо очевидного литерала объекта это еще и Block. Что там у нас по спекам на Statement?

[embed]ECMAScript 2015 Language Specification - ECMA-262 6th Edition THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT…www.ecma-international.org

Statement[Yield, Return] :
    BlockStatement[?Yield, ?Return]
    VariableStatement[?Yield]
    EmptyStatement
    ...

То есть парсер, увидев Token::LBRACE, расценивает код дальше как BlockStatement, который, ожидаемо, ничего не делает и ничего не возвращает (звучат шутки про меня).

Ну а дальше уже было делом техники зайти на https://astexplorer.net/ и запустить анализ AST для {}.1

А надо было сразу анализировать синтаксическое дерево.

А надо было сразу анализировать синтаксическое дерево.

Также для лучшего понимания стоит упомянуть 11.9.1 и 11.9.2

После ASI код превращается во что-то типа

{;}.1;
// -> 0.1

Вместо вывода

Если кажется, что вас JavaScripit, то стоит почитать документацию. И смазать.

[] + {}
// -> "[object Object]"
{} + []
// 0

От перемены мест слагаемых сумма не меняется? JS выше этих ваших переместительных законов! Ладно, ладно, тут же еще и приведение типов есть, поэтому

({} + []) === ([] + {})
// -> true
([] + {}) === ({} + [])
// -> true

Зри в контекст.

Полезно почитать:

  1. https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch5.md#contextual-rules

메타데이터
post_id
b5a74382d64a
slug
javascript-или-javascripit-b5a74382d64a
url
https://medium.com/@govnokoder/javascript-%D0%B8%D0%BB%D0%B8-javascripit-b5a74382d64a
canonical_url
https://medium.com/@govnokoder/javascript-%D0%B8%D0%BB%D0%B8-javascripit-b5a74382d64a
author_url
https://medium.com/@govnokoder
status
ok
fetched_at
2026-09-10 04:51:30