Обсяг функцій Javascript та підйом


90

Я щойно прочитав чудову статтю про обсяг та підняття JavaScript Бен Черрі, в якій він подає такий приклад:

var a = 1;

function b() {
    a = 10;
    return;

    function a() {}
}
b();
alert(a);

Використовуючи наведений вище код, браузер сповістить "1".

Я досі не впевнений, чому він повертає "1". Деякі речі, які він каже, приходять йому на думку: Усі оголошення функції підняті вгору. Ви можете застосувати змінну до функції за допомогою функції. Досі не натискає на мене.

Відповіді:


120

Підйом функції означає, що функції переміщуються у верхню частину сфери їх дії. Це є,

function b() {  
   a = 10;  
   return;  
   function a() {} 
} 

буде переписаний переписувачем до цього

function b() {
  function a() {}
  a = 10;
  return;
}

Дивно, так?

Крім того, у цьому випадку

function a() {}

поводився так само, як

var a = function () {};

Отже, по суті, це те, що робить код:

var a = 1;                 //defines "a" in global scope
function b() {  
   var a = function () {}; //defines "a" in local scope 
   a = 10;                 //overwrites local variable "a"
   return;      
}       
b();       
alert(a);                 //alerts global variable "a"

2
Тож усі декларації функції врешті присвоюються змінній?
розробник. Затвор,

15
@ dev.e.loper Так, у Javascript функції є об'єктами першого класу, як і рядки та числа. Це означає, що вони визначаються як змінні і можуть передаватися іншим функціям, зберігатися в масивах тощо.
Пітер Олсон,

4
Тіло функції жодним чином не перезаписується. Різні стандарти ECMAScript чітко зазначають, що декларації змінних та функцій обробляються до початку виконання коду. Тобто нічого не рухається , мова йде про порядок страти (звідси моя неприязнь до терміна "підняття", що робить висновок про рух чи перестановку). У вашому переписаному коді декларація var aповинна бути перед функцією, а призначення a = 1- після. Але зауважте, що це не вказано так, щоб насправді відбувалося парсером, маркером, інтерпретатором, компілятором, що завгодно, це просто еквівалент.
RobG

3
@RobG Звичайно, я думаю, ви могли б назвати опис невеликою "брехнею дітям" , але врешті-решт поведінка однакова, незалежно від того, чи переставлений код буквально, або просто порядок виконання. Те, що насправді відбувається за лаштунками, більше стосується академічних питань і може навіть залежати від реалізації.
Пітер Олсон,

7
"Крім того, у цьому випадку function a() {}поводився так само, як var a = function () {};"  - це неправильно двома способами: по-перше, якщо що, це було б var a = function a() {};(функція насправді не анонімна), по-друге, ці дві форми не є взаємозамінними, оскільки від var a = function a() {};тільки var a;частина була б піднята. Ця a = function a() {};частина все ще стояла б за заявою про повернення. Оскільки вихідна форма є декларацією функції, а не виразом функції, вона фактично піднімається в цілому.
user4642212

6

Вам слід пам’ятати, що він аналізує всю функцію і вирішує всі оголошення змінних перед її виконанням. Тому....

function a() {} 

справді стає

var a = function () {}

var a примушує його до локальної області, а область змінної проходить через всю функцію, тому глобальна змінна все ще дорівнює 1, оскільки ви оголосили a в локальну область, зробивши функцією.


5

Функція aпіднята всередині функції b:

var a = 1; 
function b() { 
   function a() {} 
   a = 10; 
   return;
} 
b(); 
alert(a);

що майже як використання var:

var a = 1; 
function b() { 
   var a = function () {};
   a = 10; 
   return;
} 
b(); 
alert(a);

Функція оголошується локально, і встановлення aвідбувається лише в локальній області, а не в глобальній змінні.


1
цей рядок "var a = function () {};" робить все зрозумілим .. в основному JavaScript є динамічною мовою, а "function" також є об'єктом у JavaScript.
рефактор

3
  1. Оголошення функції function a(){}спочатку піднімається, і воно поводиться як var a = function () {};, отже a, створюється локальна область .
  2. Якщо у вас є дві змінні з однаковим іменем (одна в глобальній, інша в локальній), локальна змінна завжди отримує перевагу над глобальною змінною.
  3. Коли ви встановлюєте a=10, ви встановлюєте локальну змінну a, а не глобальну.

Отже, значення глобальної змінної залишається незмінним, і ви отримуєте попередження 1


1

function a() { }є оператором функції, який створює aзмінну, локальну для bфункції.
Змінні створюються при синтаксичному аналізі функції, незалежно від того, varчи виконується оператор функції.

a = 10 встановлює цю локальну змінну.


фактично a = 10встановлює змінну в глобальній області, коли функція bвиконується, якщо ви не додаєте "use strict"(в таких середовищах, як підтримка цієї директиви).
Шон Віейра,

@Sean: Ні, оскільки оператор функції створює локальний ідентифікатор.
Слакс

... і .... ти маєш рацію. Не усвідомлював цього особливого наслідку підняття функції. Дякую!
Шон Віейра,

1

У чому полягає суперечка у цьому маленькому фрагменті коду?

Випадок 1:

Включіть function a(){}визначення всередину тіла function bнаступним чином.logs value of a = 1

var a = 1;
function b() {
  a = 10;
  return;

  function a() {}
}
b();
console.log(a); // logs a = 1

Випадок 2

Виключіть function a(){}визначення всередині тіла function bнаступним чином.logs value of a = 10

var a = 1;
function b() {
  a = 10;  // overwrites the value of global 'var a'
  return;
}
b();
console.log(a); // logs a = 10

Спостереження допоможе вам усвідомити, що оператор console.log(a)журналює наступні значення.

Випадок 1: a = 1

Випадок 2: a = 10

Позиції

  1. var a було визначено та оголошено лексично в глобальному масштабі.
  2. a=10 Це твердження перепризначає значення до 10, воно лексично розміщується всередині функції b.

Пояснення обох випадків

Через function definition with name propertya те саме, що і variable a. Внутрішня variable aчастина function body bстає локальною змінною. З попереднього рядка випливає, що глобальне значення залишку залишається незмінним, а місцеве значення а оновлюється до 10.

Отже, ми маємо намір сказати, що це код нижче

var a = 1;
function b() {
  a = 10;
  return;

  function a() {}
}
b();
console.log(a); // logs a = 1

Він тлумачиться перекладачем JS наступним чином.

var a = 1;
function b() {
  function a() {}
  a = 10;
  return;


}
b();
console.log(a); // logs a = 1

Однак, коли ми прибираємо function a(){} definition, то value of 'a'оголошується і визначена поза функцією видання, що значення набуває перезаписані і змінюється до 10 в разі 2. Значення отримує перезаписані , тому що a=10відноситься до Всесвітньої декларації , і якщо б вона була оголошена локально ми повинні мати письмовий var a = 10;.

var a = 1;
function b() {
  var a = 10; // here var a is declared and defined locally because it uses a var keyword. 
  return;
}
b();
console.log(a); // logs a = 1

Ми можемо уточнити наше сумнів в подальшому, змінюючи name propertyпо прибуттю function a(){} definitionдо якого - небудь іншому імені , ніж'a'

var a = 1;
function b() {
  a = 10; // here var a is declared and defined locally because it uses a var keyword. 
  return;

  function foo() {}
}
b();
console.log(a); // logs a = 1

1

Підйом - це концепція, створена для нас, щоб полегшити розуміння. Що насправді відбувається, так це те, що декларації робляться спочатку щодо їх обсягу, а призначення виконуються після цього (не одночасно).

Коли оголошення відбуваються, var aтоді function bі всередині цього bобсягу function aоголошується.

Ця функція a буде затінювати змінну a, що надходить із глобальної області.

Після завершення оголошень розпочнеться присвоєння значень, глобальний aотримає значення, 1а внутрішній function bотримає 10. коли ви це зробите alert(a), він викличе фактичну глобальну змінну області. Ця невелика зміна коду зробить його більш зрозумілим

        var a = 1;

    function b() {
        a = 10;
        return a;

        function a() { }
    }

    alert(b());
    alert(a);

1
Цікаво, що так багато експертів навіть на курсі kodschool.com посилаються на підйом, який є не що інше, як спрощений погляд на те, що відбувається, насправді підйом не відбувається взагалі. Посилання: 1) developer.mozilla.org/en-US/docs/Glossary/Hoisting 2) Глава 5 таємниць JavaScript Ninja 2 / e, Джон відставка, ведмідь bebeault, Джосіп Марас
adnan2

1

Дивно, що жодна з відповідей тут не згадує про відповідність контексту виконання у ланцюзі обсягу.

JavaScript Engine обгортає виконуваний на даний момент код у контексті виконання. Базовим контекстом виконання є глобальний контекст виконання. Кожного разу, коли викликається нова функція, створюється новий контекст виконання та поміщається в стек виконання. Подумайте про кадр стека, який сидить на стеку викликів іншими мовами програмування. Останній у першому виході. Тепер кожен контекст виконання має свої змінні середовища та зовнішнє середовище в JavaScript.

Я буду використовувати наведений нижче приклад як демонстрацію.

1) Спочатку ми входимо у фазу створення глобального контексту виконання. Створено як зовнішнє середовище, так і змінне середовище лексичного середовища. Глобальний об'єкт налаштовується і поміщається в пам'ять із вказівкою на нього спеціальної змінної "this" Функція a та її код та змінна myVar із невизначеним значенням поміщаються до пам'яті у глобальному середовищі змінних. важливо зауважити, що код функції a не виконується. Він просто поміщений у пам'ять з функцією a.

2) По-друге, це фаза виконання контексту виконання. myVar більше не є невизначеним значенням. Він ініціалізується зі значенням 1, яке зберігається у глобальному середовищі змінних. Викликається функція a і створюється новий контекст виконання.

3) У контексті виконання функції a проходить фазу створення та виконання власного контексту виконання. Він має власне зовнішнє середовище та змінне середовище, отже, своє власне лексичне середовище. Функція b та змінна myVar зберігаються у своєму змінному середовищі. Це змінне середовище відрізняється від глобального змінного середовища. Оскільки функція a лексично (фізично в коді) знаходиться на тому самому рівні, що і глобальний контекст виконання, її Зовнішнє середовище є глобальним контекстом виконання. Таким чином, якщо функція a мала посилатися на змінну, яка відсутня у своєму середовищі змінних, вона здійснить пошук у ланцюзі обсягу та спробує знайти змінну в середовищі змінних глобального контексту виконання.

4) Функція b викликається у функції a. Створюється новий контекст виконання. Оскільки він лексично сидить у функції a, його Зовнішнє середовище є a. Отже, коли він посилається на myVar, оскільки myVar не знаходиться у змінному середовищі функції b, він буде виглядати у змінному середовищі функції a. Він знаходить його там і друкує console.log 2. Але якщо змінна не була у змінному середовищі функції a, то оскільки Зовнішнє середовище функції a є глобальним контекстом виконання, то ланцюжок обсягу продовжить пошук там.

5) Після завершення виконання функцій b та a вони вискакують із стеку виконання. Однопоточний механізм JavaScript продовжує виконувати в глобальному контексті виконання. Він викликає функцію b. Але у глобальному середовищі змінних немає функції b і немає іншого зовнішнього середовища для пошуку в глобальному контексті виконання. Таким чином, виняток викликає JavaScript Engine.

function a(){
  function b(){
    console.log(myVar);
  }

  var myVar = 2;
  b();
}

var myVar = 1;
a();
b();
> 2
> Uncaught ReferenceError: b is not defined

Наведений нижче приклад показує дію ланцюга обсягу. У змінному середовищі контексту виконання функції b немає myVar. Тому він здійснює пошук у своєму Зовнішньому середовищі, яке є функцією a. Функція a також не має myVar у своєму змінному середовищі. Отже, механізм пошуку функції зовнішнього середовища a, що є зовнішнім середовищем глобального контексту виконання, і там визначено myVar. Отже, console.log друкує 1.

function a(){
  function b(){
    console.log(myVar);
  }

  b();
}

var myVar = 1;
a();
> 1

Щодо контексту виконання та пов'язаного з ним лексичного середовища, включаючи зовнішнє середовище та середовище змінних, увімкніть масштабування змінних у JavaScript. Навіть якщо ви викликаєте одну і ту ж функцію кілька разів, для кожного виклику вона створюватиме власний контекст виконання. Отже, кожен контекст виконання матиме власну копію змінних у своєму середовищі змінних. Немає спільного використання змінних.


0

Це відбувається через те, що ім'я змінної збігається з тим, що ім'я функції означає "а". Таким чином, через підняття Javascript він намагається вирішити конфлікт імен, і він поверне a = 1.

Мене це також бентежило, поки я не прочитав цю публікацію на тему "Підняття JavaScript" http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html

Сподіваюся, це допоможе.


0

Ось мій підсумок відповіді з більшою кількістю анотацій та привабливою скрипкою, з якою можна пограти.

// hoisting_example.js

// top of scope ie. global var a = 1
var a = 1;

// new scope due to js' functional (not block) level scope
function b() {
    a = 10; // if the function 'a' didn't exist in this scope, global a = 10
  return; // the return illustrates that function 'a' is hoisted to top
  function a(){}; // 'a' will be hoisted to top as var a = function(){};
}

// exec 'b' and you would expect to see a = 10 in subsequent alert
// but the interpreter acutally 'hoisted' the function 'a' within 'b' 
// and in doing so, created a new named variable 'a' 
// which is a function within b's scope
b();

// a will alert 1, see comment above
alert(a);

https://jsfiddle.net/adjavaherian/fffpxjx7/


0

scpope & закриття та підйом (var / function)

  1. scpope: глобальний var може мати доступ у будь-якому місці (весь обсяг файлу), локальний var може бути доступний лише за допомогою локальної області (функція / область блоку)!
    Примітка: якщо локальна змінна не використовує ключові слова var у функції, вона стане глобальною змінною!
  2. закриття: функція з внутрішньої сторони іншої функції, яка може отримати доступ до локальної області (батьківська функція) та глобальної області, однак, до її змін не можуть отримати доступ інші! хіба що, поверніть його як значення, що повертається!
  3. піднімання: перемістіть усі декларувані / недекларовані vars / функції у верхню частину області, ніж присвоюйте значення або null!
    Примітка: це просто переміщення оголошення, а не переміщення значення!

var a = 1;                
//"a" is global scope
function b() {  
   var a = function () {}; 
   //"a" is local scope 
   var x = 12; 
   //"x" is local scope 
   a = 10;
   //global variable "a" was overwrited by the local variable "a"  
   console.log("local a =" + a);
   return console.log("local x = " + x);
}       
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x = 
console.log(x);
// ReferenceError: x is not defined



0

Підняття в JavaScript означає, що оголошення змінних виконуються через програму до того, як виконується будь-який код. Тому оголошення змінної в будь-якому місці коду еквівалентно оголошенню її на початку.


0

Все залежить від сфери дії змінної 'a'. Дозвольте пояснити, створюючи сфери як зображення.

Тут JavaScript створить 3 сфери.

i) Глобальний обсяг. ii) Функція b () сфера дії. iii) Функція a () сфера дії.

введіть тут опис зображення

Зрозуміло, коли ви викликаєте область сповіщення методу сповіщення на той час належить Global, тому він вибере значення змінної "a" лише із глобальної області, яке дорівнює 1.


0

Довгий пост!

Але це очистить повітря!

Принцип роботи Java Script полягає в тому, що він включає двоетапний процес:

  1. Компіляція (так би мовити) - Цей крок реєструє змінні та оголошення функцій та їх відповідний обсяг. Воно не включає функцію , оцінюючи вираз: var a = function(){}(наприклад , привласнення або змінне вираз 3для xв разі var x =3;, який не що інше, як оцінка RHS частини)

  2. Перекладач: Це частина виконання / оцінки.

Перевірте вихідні дані коду нижче, щоб зрозуміти:

//b() can be called here!
//c() cannot be called.
console.log("a is " + a);
console.log("b is " + b);
console.log("c is " + c);
var a = 1;
console.log("Now, a is " + a);
var c = function() {};
console.log("Now c is " + c);

function b() {
  //cannot write the below line:
  //console.log(e); 
  //since e is not declared.
  e = 10; //Java script interpreter after traversing from this function scope chain to global scope, is unable to find this variable and eventually initialises it with value 10 in global scope.
  console.log("e is " + e) //  works!
  console.log("f is " + f);
  var f = 7;
  console.log("Now f is " + f);
  console.log("d is " + d);
  return;

  function d() {}
}
b();
console.log(a);

Давайте порушимо це:

  1. На етапі компіляції `` a '' буде зареєстровано у глобальному масштабі зі значенням ' undefined'. Те саме стосується і ` c`, його значення на даний момент буде ' undefined', а не ` function()` ' '. ' b' буде зареєстровано як функцію в глобальному масштабі. Усередині b'' scope, ' f' буде зареєстровано як змінну, яка на даний момент не визначена, а функція ' d' буде зареєстрована.

  2. Під час запуску інтерпретатора function()можна отримати доступ до оголошених змінних та (а не виразів) до того, як інтерпретатор досягне фактичного рядка виразу. Отже, змінні будуть надруковані ' undefined', а анонсовану функцію можна буде викликати раніше. Однак спроба отримати доступ до незадекларованої змінної до ініціалізації її виразу призведе до такої помилки:

console.log(e)
e = 3;

Тепер, що відбувається, коли у вас є декларація змінної та функції з однаковим іменем.

Відповідь - функції завжди піднімаються раніше, і якщо одна і та ж змінна імені оголошена, вона трактується як дублікат і ігнорується. Пам’ятайте, порядок не має значення. Функціям завжди надається пріоритет. Але на етапі оцінки ви можете змінити посилання на змінну на що завгодно (в ньому зберігається все, що було останнім призначенням). Погляньте на наведений нижче код:

var a = 1;
console.log("a is " + a);

function b() {
  console.log("a inside the function b is " + a); //interpreter finds                                'a' as function() in current scope. No need to go outside the scope to find 'a'.
  a = 3; //a changed
  console.log("Now a is " + a);
  return;

  function a() {}
}
var a; //treated as duplicate and ignored.
b();
console.log("a is still " + a + " in global scope"); //This is global scope a.


0

Підйом - це поведінкова концепція JavaScript. Підйом (скажімо, переміщення) - це концепція, яка пояснює, як і де слід оголошувати змінні.

У JavaScript змінна може бути оголошена після її використання, оскільки декларації функцій та декларації змінних завжди переміщуються (“підняті”) невидимо у верхню частину їхньої області дії інтерпретатором JavaScript.

У більшості випадків ми зустрічаємо два типи підйому.

1.Змінна декларація підняття

Давайте зрозуміємо це за цим фрагментом коду.

 a = 5; // Assign 5 to a
 elem = document.getElementById("demo"); // Find an element 
 elem.innerHTML = a;                     // Display a in the element
 var a; // Declare a
  //output-> 5

Тут оголошення змінної a розміщуватиметься зверху невидимо інтерпретатором javascript під час компіляції. Тож ми змогли отримати значення a. Але такий підхід до декларування змінних не рекомендується, оскільки ми повинні оголошувати змінні вгорі вже так.

 var a = 5; // Assign and declare 5 to a
 elem = document.getElementById("demo"); // Find an element 
 elem.innerHTML = a;                     // Display a in the element
  // output -> 5

розглянемо інший приклад.

  function foo() {
     console.log(x)
     var x = 1;
 }

насправді трактується так:

  function foo() {
     var x;
     console.log(x)
     x = 1;
  }

У цьому випадку х не буде визначено

Не має значення, чи виконаний код, який містить оголошення змінної. Розглянемо цей приклад.

  function foo() {
     if (false) {
         var a = 1;
     }
     return;
     var b = 1;
  }

Ця функція виявляється такою.

  function foo() {
      var a, b;
      if (false) {
        a = 1;
     }
     return;
     b = 1;
  }

У декларації змінної піднімаються лише визначення змінної, а не присвоєння.

  1. Оголошення функції підняття

На відміну від змінної підйому, тіло функції або присвоєне значення також буде піднято. Розглянемо цей код

 function demo() {
     foo(); // this will give error because it is variable hoisting
     bar(); // "this will run!" as it is function hoisting
     var foo = function () {
         alert("this would not run!!");
     }
     function bar() { 
         alert("this will run!!");
     }
 }
 demo();

Тепер, коли ми зрозуміли як підняття змінних, так і функцій, давайте розберемося зараз у цьому коді.

var a = 1;
function b() {
  a = 10;
  return;
   function a() {}
}
b();
alert(a);

Цей код виявиться таким.

var a = 1;                 //defines "a" in global scope
 function b() {  
   var a = function () {}; //defines "a" in local scope 
    a = 10;                 //overwrites local variable "a"
    return;      
 }       
 b();       
 alert(a); 

Функція a () матиме локальний обсяг всередині b (). a () буде переміщено вгору під час інтерпретації коду з його визначенням (лише у випадку підняття функції), тому a тепер матиме локальний обсяг і, отже, не впливатиме на глобальний обсяг деякого часу, маючи власний обсяг всередині функції b () .


0

З мого знання, підняття відбувається з оголошеннями змінних та функціями, наприклад:

a = 7;
var a;
console.log(a) 

Що відбувається в двигуні JavaScript:

var a;
a = 7;
console.log(a);
// 7

Або:

console.log(square(7)); // Output: 49
function square(n) { return n * n; }

Це стане:

function square(n) { return n * n; }
console.log(square(7)); // 49

Але такі призначення, як присвоєння змінної, присвоєння виразу функції, не будуть підняті: Наприклад:

console.log(x);
var x = 7; // undefined

Це може стати таким:

var x;
console.log(x); // undefined
x = 7;

0

Для опису хостингу в javascript в одному реченні використовуються змінні та функції, підняті до верхньої частини області, в якій вони оголошені.

введіть тут опис зображення

Я припускаю, що ви новачок, щоб зрозуміти правильне підняття спочатку ми зрозуміли різницю між undefined та ReferenceError

 var v;
 console.log(v);
 console.log(abc);
/*
The output of the above codes are:
undefined
ReferenceError: abc is not defined*/

тепер у наведеному нижче коді те, що ми бачимо? змінна і вираз функції є декларним.

<script>
var totalAmo = 8;
var getSum = function(a, b){
      return a+b;
}
</script>

але реальна картина з доказом того, що як змінна, так і функція розміщені вгорі там:

console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
      return a+b;
}
console.log(totalAmo);
console.log(getSum(9,7));

Вихідні дані двох перших журналів невизначені, а TypeError: getSum не є функцією, оскільки і var totalAmo, і getSum розміщені у верхній частині області, як показано нижче

 <script>
        var totalAmo;
        var getSum;

        console.log(totalAmo);
        console.log(getSum(8,9));
        var totalAmo = 8;
        var getSum = function(a, b){
            return a+b;
        }
        console.log(totalAmo);
        console.log(getSum(9,7));
    </script>

Але для оголошення функцій цілі функції були підняті вгорі своєї області дії.

console.log(getId());
function getId(){
   return 739373;
}
/* output: 739373, because the whole function hoisted on the top of the scope.*/

Тепер та сама логіка стосується тих змінних, експересій функцій та оголошень функцій, оголошених всередині функціональної області. Ключовий момент: вони не будуть підняті у верхній частині файлу ;

function functionScope(){
            var totalAmo;
            var getSum;

            console.log(totalAmo);
            console.log(getSum(8,9));
            var totalAmo = 8;
            var getSum = function(a, b){
                return a+b;
            }
        }

Отже, коли ви використовуєте ключове слово var , змінну та функцію, підняту зверху до області дії (глобальна область дії та область функцій). А як щодо хай і конст , const і let все ще знають про глобальну область дії та область функцій, як і var, але змінні const і let також знають про іншу область, яка називається заблокованою сферою. область дії блоку присутня всякий раз, коли є блок коду, наприклад, для циклу, якщо оператор else, цикл while тощо.

Коли ми використовуємо const і let, щоб оголосити змінну в цій області блоку, оголошення змінної буде піднято лише у верхній частині цього блоку, в якому вона знаходиться, і вона не буде піднята вгорі батьківської функції або вгорі глобальний обсяг, який він підняв.

 function getTotal(){
            let total=0;
            for(var i = 0; i<10; i++){
                let valueToAdd = i;
                var multiplier = 2;
                total += valueToAdd*multiplier;
            }
            return total;
        }

Змінні в прикладі abobe будуть підняті як нижче

 function getTotal(){
            let total;
            var multiplier;
            total = 0;
            for(var i = 0; i<10; i++){
                let valueToAdd;
                valueToAdd = i;
                multiplier = 2;
                total += valueToAdd*multiplier;
            }
            return total;
        }

0

ES5: піднімання функцій та змінне підняття

function hoistingпріоритет greaterніжvariable hoisting

"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2016-06-01
 * @modified
 *
 * @description function-hoisting.js
 * @augments
 * @example
 * @link
 *
 */

(function() {
  const log = console.log;

  var a = 1;
  function b() {
    a = 10;
    log(`local a`, a)
    return;
    // function hoisting priority is greater than variable hoisting
    function a() {}
  }
  b();
  log(`global a`, a);
  // local a 10
  // global a 1
})();



що дорівнює

(function() {
  const log = console.log;

  // define "a" in global scope
  var a = 1;
  function b() {
    // define "a" in local scope
    var a ;
    // assign function to a
    a = function () {};
    // overwrites local variable "a"
    a = 10;
    log(`local a`, a);
    return;
  }

  b();
  // log global variable "a"
  log(`global a`, a);

  // local a 10
  // global a 1
})();

причина підняття

var a = 1;                
//"a" is global scope
function b() {  
   var a = function () {}; 
   //"a" is local scope 
   var x = 12; 
   //"x" is local scope 
   a = 10;
   //global variable "a" was overwrited by the local variable "a"  
   console.log("local a =" + a);
   return console.log("local x = " + x);
}       
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x = 
console.log(x);
// ReferenceError: x is not defined

/**
 *  scpope & closure & hoisting (var/function)
 *  
 * 1. scpope : the global var can be access in any place(the whole file scope), local var only can be accessed by the local scope(function/block scope)!
 * Note: if a local variable not using var keywords in a function, it will become a global variable!
 * 
 * 2. closure : a function inner the other function, which can access local scope(parent function) & global scope, howerver it's vars can't be accessed by others! unless, your return it as return value!
 * 
 * 3. hoisting : move all declare/undeclare vars/function to the scope top, than assign the value or null!
 * Note: it just move the declare, not move the value!
 * 
 */

ES6 let, constпідйомник не існує

(() => {
  const log = console.log;
  log(a)
  // Error: Uncaught ReferenceError: Cannot access 'a' before initialization
  let a = 1;
})();



(() => {
  const log = console.log;
  log(b)
  // Error: Uncaught ReferenceError: Cannot access 'b' before initialization
  const b = 1;
})();

посилання

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.