01

Область видимости, hoisting, типы

Где живёт имя, что успевает подняться и как плюс меняет типы.

var и let крепятся к разным местам. var принадлежит функции или всему скрипту, let и const — блоку: if, for или просто фигурным скобкам. Имя, объявленное внутри, затеняет внешнее, и снаружи внутреннее не видно. Но до своей строки внутреннее имя уже существует — именно поэтому обращение к нему не «берёт внешнее», а падает.

Подъём

  • function foo() {} поднимается целиком: её можно вызвать выше строки объявления.
  • var поднимается только как объявление. До присваивания значение undefined, а не ошибка.
  • let и const входят в область, но до своей строки лежат в TDZ — временной мёртвой зоне. Чтение даёт ReferenceError.
  • Выражение не поднимается вообще. const f = () => {} до своей строки — TDZ, а не функция.

Ловушка: typeof необъявленного имени возвращает "undefined" и не бросает, но имя в TDZ от typeof не спасает — будет ReferenceError.

Приведение типов

Оператор + перегружен. Если хотя бы одна сторона — строка, будет склейка, а не сложение: true + '1' даёт "true1". Остальные арифметические операторы всегда приводят к числу: '5' - 2 это 3, а '5' + 2 это "52".

Как операторы приводят объекты:

[] + []        // ""        — обе стороны стали пустыми строками[] + {}        // "[object Object]"[1, 2] + [3]   // "1,23"+[]            // 0

Ложных значений ровно восемь: false, 0, -0, 0n, "", null, undefined, NaN. Всё остальное истинно, включая [] и {}.

== приводит типы, === — нет. Из-за шага приведения == не транзитивен:

0 == ""     // true0 == "0"    // true"" == "0"   // false

Сравнения <, >, <=, >= числовые, поэтому null == 0 ложно, а null >= 0 истинно: null приводится к 0. Отдельно: NaN не равен ничему, даже себе.

  1. 1.1var поднимается, let в TDZсейчас
  2. 1.2Два let с одним именем
  3. 1.3function declaration и var-функция
  4. 1.4Локальный var затеняет внешний
  5. 1.5typeof, плюс и нестрогое равенство
  6. 1.6typeof необъявленного и typeof в TDZ
  7. 1.7var не видит блок, let видит
  8. 1.8const и стрелка не поднимаются
  9. 1.9function и var с одним именем
  10. 1.10Присваивание без объявления
  11. 1.11Переменная цикла снаружи for
  12. 1.12var из невыполненного if
  13. 1.13Лексическая область, не место вызова
  14. 1.14const запрещает другое присваивание
  15. 1.15typeof от typeof и разные типы
  16. 1.16true, null и undefined в плюсе
  17. 1.17Строки в арифметике и унарный плюс
  18. 1.18== не транзитивно
  19. 1.19Массив в == и в плюсе
  20. 1.20Что truthy на самом деле
  21. 1.21NaN, Number.isNaN и isNaN
  22. 1.22let внутри case: со скобками и без
  23. 1.23delete: переменная против свойства
  24. 1.24Присваивание параметру: число и объект
  25. 1.25Дефолты в деструктуризации: undefined и null
  26. 1.26Object.is смотрит иначе, чем ===
  27. 1.270 и пустая строка: ?? против ||

Задачи из сборки