Много было сказано о подъеме в JavaScript, но это все еще остается совершенно неизвестной темой и причиной многих ошибок во многих приложениях Javascript.

Давайте пройдемся по нему, а затем посмотрим, как это работает с var, а затем с let / const.

Прежде чем мы начнем с подъема, давайте рассмотрим, что означает "область действия" в Javascript.

Область действия. Проще говоря, "область действия" - это видимость переменной в JavaScript. Это означает, что он определяет, где в коде можно получить доступ к этой переменной и, следовательно, ее значение может быть прочитано или изменено.
Переменные в JavaScript могут иметь локальную или глобальную область видимости в зависимости от того, где они определены.
Все переменные, определенные (с помощью 'var') в функции, имеют область действия, ограниченную этой функцией, и, как говорят, имеют локальную область действия.
Считается, что все переменные, которые определены вне какой-либо функции (например, непосредственно внутри тега скрипта в HTML), имеют глобальную область действия.

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

<script>
   var globalVariable = "Hello! I'm a global!";
   function scoper() {//is that even a word?
      var localVariable = "I'm inside a function, so I'm limited to local scope."
      console.log(globalVariable); 
      console.log(localVariable); 
   }
   scoper(); //Hello! I'm a global!
             //I'm inside a function, so I'm limited to local scope.   
   console.log(globalVariable); //Hello! I'm a global!
   console.log(localVariable); //Uncaught ReferenceError: localVariable is not defined
</script>

Область действия в let и const:

Scope по-разному работает с let и const, оба из которых были введены как часть спецификации ES6.

И let, и const имеют область действия блока, что просто означает, что их область действия ограничена блоком (и подблоками), оператором или выражением, в котором они используются.

Чтобы понять, что мы подразумеваем под блоком в JavaScript, просто перейдите от оператора let вверх и найдите первую открывающую скобку ({); Оператор let будет ограничен по объему оператором let, а соответствующая закрывающая скобка (}) - открывающей скобкой ({), которую вы нашли. Набор скобок может быть функцией или просто циклом for.

Например,

<script>
function myBigFunc(){
  if(true){
    let blockScopedVariable = 1;
  }
  if(true){
    var functionScopedVariable = 2;
  }
  console.log(blockScopedVariable); //Uncaught ReferenceError: blockScopedVariable is not defined
  console.log(functionScopedVariable); //2
}  
</script>

Переменная blockScopedVariable была объявлена ​​с помощью let и, следовательно, доступна для доступа только внутри своего блока, который представляет собой пару фигурных скобок ({}), заключающих ее.

Переменная «functionScopedVariable» была объявлена ​​с «var», что дало ей локальную область видимости. Таким образом, он доступен внутри всего «myBigFunc».

Теперь, когда мы прочитали, что мы подразумеваем под областью действия, а также увидели простой пример, давайте вернемся к нашей исходной теме.

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

<script>
  console.log(x); //undefined
  var x;
</script>

JavaScript автоматически перемещает все объявления переменных наверх, поэтому, хотя мы пытались получить доступ к значению переменной «x» до того, как мы фактически написали для нее объявление, это не привело к ошибке. Чудесно! Теперь посмотрим, что происходит, когда мы инициализируем «x».

<script>
  console.log(x); //undefined
  var x = 2;
</script>

Упомянутое выше поведение является причиной множества ошибок в JavaScript. JavaScript поднимает объявление (var x), но НЕ инициализацию (= 2) переменной.

Приведенный выше код эквивалентен

<script>
  var x;
  console.log(x); //undefined
  x = 2;
</script>

Именно так работает подъем в JavaScript. Разработчики могут создавать простые правила, например всегда инициализировать переменные в верхней части области видимости, что может помочь избежать таких проблем, особенно при работе в больших командах.

Другое решение - использовать let или const. И "let", и "const" не поднимаются. Доступ к ним до того, как они были объявлены, просто вызывает ошибку во время выполнения, что помогает избежать ошибок, которые могут возникнуть из-за подъема.

Подъем с помощью функций:

JavaScript позволяет нам писать функции двумя разными способами. Давайте посмотрим, как подъемник работает с ними обоими:

Объявление функции: объявление функции в JavaScript имеет вид:

function [optional functionName] (params) {
//function body
}

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

<script>
  console.log(myAdditionFunc(5, 7); //12
  .
  //other statements
  .
  .
  function myAdditionFunc (num1, num2){
    return num1 + num2;
  }
</script> 

Выражение функции. Выражение функции - это когда функция назначается как объект переменной «var» (или «let» / «const»).

var myFunc = function (params){
//function body
}

Подъем здесь зависит от того, какой из «var» или «let» / «const» используется для объявления.

Например:

<script>
  function myBigFunction() {
    
    console.log(additionFunc(2,5)); //7
    //addition function was defined using Function declaration.
    
    console.log(subtractionFunc(5,2)); //Uncaught TypeError: subtractionFunc is not a function.  
    //This error shows that subtractionFunc is declared but is not recognized as a function yet.
    console.log(subtractionFunc) //undefined
    console.log(multiplicationFunc(2,5)); //Uncaught ReferenceError: multiplicationFunc is not defined
       
    function additionFunc(a, b){
      return a + b;
    }
    var subtractionFunc = function(a, b){
      return a - b;
    }
    let multiplicationFunc = function(a, b){
      return a * b;
    }
    console.log(additionFunc(2,5)); //7
    console.log(subtractionFunc(5,3)); //2
    console.log(multiplicationFunc(2, 5)); //10
  }
</script>

Функция «addFunc» была определена с помощью «объявления функции» и, таким образом, поднимается, что позволяет нам вызывать ее перед ее определением.

Функция «subtractionFunc» была определена с использованием «выражения функции» с «var», и поэтому ее объявление поднимается, давая ей значение undefined до ее инициализации.

Функция multiplicationFunc была определена с помощью выражения function с let и поэтому не поднимается вообще.

Вот и все подъемы!

Ваше здоровье!