Прежде чем читать эту статью, прочитайте следующую статью:
JavaScript Named Binding, Scope, and Closure

Что такое подъем?

Подъем в JavaScript – это процесс, при котором интерпретатор перемещает объявление функций, переменных или классов в верхнюю часть своей области видимости перед выполнением кода.

Термин Поднятие не является нормативно определенным в спецификации ECMAScript. Спецификация определяет группу объявлений как HoistableDeclaration,

Подъем — это термин, обычно используемый в контексте языка программирования JavaScript. Это относится к поведению перемещения объявлений переменных и функций в верхнюю часть области их содержания на этапе компиляции до выполнения кода.

Типы подъема:

  1. Подъем стоимости (функция)
  2. Поднятие объявления (var)
  3. Изменения поведения области действия (let, const и class)

Повышение ценности

Возможность использовать значение переменной в ее области до объявления строки.

Поднятие декларации

Возможность ссылаться на переменную в ее области действия до того, как строка будет объявлена, без выдачи ReferenceError, но значение всегда равно undefined.

Изменения в поведении области действия

Объявление переменной приводит к изменению поведения в ее области видимости перед строкой, в которой она объявлена.

В JavaScript, когда вы объявляете переменную, используя ключевое слово var, или функцию, используя ключевое слово function, независимо от того, где эти объявления появляются в пределах области (например, функции или глобальной области), они поднимаются наверх этой области. Это означает, что они фактически обрабатываются так, как если бы они были объявлены в начале области видимости, даже если их фактическое объявление появляется позже в коде. Некоторые предпочитают рассматривать let, const и class как неподъемные, потому что временная мертвая зона строго запрещает любое использование переменной до ее объявления. Это несогласие нормально, поскольку термин «подъем» не является общепринятым. Однако временная мертвая зона может вызвать другие наблюдаемые изменения в ее масштабе.

Важно отметить, что поднимаются только объявления, а не инициализации.

Стоит отметить, что подъем ведет себя по-разному для переменных, объявленных с помощью ключевых слов let и const в ECMAScript 2015 (ES6), по сравнению с var. Они поднимаются, но в отличие от var не инициализируются с помощью undefined. Вместо этого выдается ReferenceError, если вы пытаетесь получить к ним доступ до их объявления.

Преимущества подъема:

  1. Гибкость структуры кода. Подъем позволяет объявлять переменные и функции в любом месте области видимости, даже после их использования. Эта гибкость может быть полезна для организации вашего кода таким образом, чтобы он имел логический смысл, а не ограничивался строгим порядком сверху вниз.
  2. Понимание области действия. Изучая подъем, вы лучше понимаете, как работают области действия JavaScript. Это поможет вам понять фазу компиляции и то, как движок JavaScript обрабатывает ваш код. Эти знания могут быть полезны при отладке и оптимизации вашего кода.
  3. Совместимость с прежними версиями. Подъем является результатом исторической разработки JavaScript. Хотя иногда это можно считать причудой, важно знать об этом, потому что старые кодовые базы и библиотеки JavaScript могут полагаться на подъем. Понимание подъема позволяет эффективно работать с устаревшим кодом.

Недостатки подъема:

  1. Читаемость и ремонтопригодность. Подъем может затруднить чтение и понимание кода, особенно для начинающих или разработчиков, которые не знакомы с таким поведением. Когда переменные и функции поднимаются, их фактическое размещение в коде может не отражать порядок их появления, что приводит к путанице и потенциальным ошибкам. Обычно рекомендуется явно объявлять переменные и функции в верхней части их соответствующих областей, чтобы улучшить читаемость и удобство сопровождения кода.
  2. Потенциальные ошибки и ошибки. Подъем может привести к появлению незаметных ошибок и ошибок, если вы полагаетесь на поднятые переменные или функции, не зная об их фактическом размещении в коде. Например, если вы ссылаетесь на переменную до того, как ей будет присвоено значение, это приведет к undefined, а не к ошибке ссылки. Это может привести к неожиданному поведению, которое трудно отследить и отладить.
  3. Потенциальные проблемы с организацией кода. Хотя подъем обеспечивает гибкость структуры кода, он также может привести к плохой организации кода, если разработчики слишком сильно полагаются на подъем и разбрасывают объявления переменных и функций по всему коду. Удобочитаемость и ремонтопригодность кода можно улучшить, следуя согласованной структуре и объявляя переменные и функции в начале их соответствующих областей.
  4. Зависимость от контекста выполнения. Поднятие зависит от контекста выполнения и конкретного движка JavaScript. Различные движки могут иметь небольшие различия в поведении подъема, что может привести к несоответствиям, если вы работаете на разных платформах или в разных средах. Понимание конкретного поведения подъема в целевой среде имеет решающее значение для написания надежного и переносимого кода.

Поведение при подъеме:

  1. var Переменные
  2. let и const переменные
  3. function Декларации
  4. class Декларации

var

  • Поднятие. Объявления переменных, использующие var, поднимаются наверх своей области видимости на этапе компиляции. Это означает, что вы можете ссылаться на переменную и использовать ее до ее фактического объявления в коде.
  • Инициализация. Поднятые переменные var по умолчанию инициализируются значением undefined.
console.log(x);   // undefined
var x = 5;

пусть и const

  • Поднятие. Объявления переменных, использующие let и const, поднимаются наверх своей области видимости на этапе компиляции, но не инициализируются. Доступ к ним до их фактического объявления приводит к ошибке ReferenceError.
  • Инициализация. В отличие от var, поднятые переменные let и const не получают значение автоматической инициализации undefined. Они остаются во «Временной мертвой зоне» до их фактического объявления в коде.
console.log(x);   // Uncaught ReferenceError: x is not defined
let x = 5;
console.log(x);   // Uncaught ReferenceError: x is not defined
const x = 5;

функция

  • Поднятие. Объявления функций полностью поднимаются наверх своей области видимости на этапе компиляции. Их можно вызывать перед их фактическим объявлением в коде.
  • Инициализация. Объявления функций также поднимаются вместе со всем определением функции, что позволяет вызывать их из любого места в пределах их области действия.
print();         // "Hello"

function print() {
  console.log("Hello");
}

сорт

  • Поднятие: объявления классов поднимаются частично, в отличие от объявлений функций, которые поднимаются полностью, и объявлений переменных с var, которые поднимаются и инициализируются с помощью undefined.
  • Инициализация: само объявление класса поднимается наверх текущей области, но инициализация класса не происходит до того момента в коде, где он определен. Это означает, что вы можете ссылаться на имя класса перед его объявлением, но вы не можете получить доступ к его методам или создать его экземпляры, пока он не будет определен.
const instance = new Message(); // Uncaught ReferenceError: MyClass is not defined

class Message {
  constructor() { }
}

Использованная литература:

  1. Подъем
  2. Подъем JavaScript
  3. Что такое подъем в JavaScript?