Углубленный JS - подъем переменных (подъем объявления функции)

внешний интерфейс ECMAScript 6
Углубленный JS - подъем переменных (подъем объявления функции)

предисловие

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

Маленький каштан переменного продвижения

console.log(a) // undefined
var a = 'hello JS' 

/* 在我们声明a之前为什么输出a不会报错呢? 不急,让我们接着往下看 */

num = 6;
num++;
var num;
console.log(num) // 7 好奇怪,为什么给一个还没有声明的变量赋值会不报错呢

function hoistFunction() {
    foo();
    function foo() {        
        console.log('running...')    
    }
}
hoistFunction(); // running... 

/* 最后一个栗子 */

alert(a) //  function a { alert(10) }
a(); // 10
var a = 3;
function a() {    
    alert(10)
};
alert(a) // 3
a = 6;
a(); // throw error


Проанализируйте причины

Движок JS сделает это один раз перед фактическим выполнением кода.предварительно скомпилировано«Простое понимание предварительной компиляции заключается в том, чтобы освободить место в памяти для хранения некоторых переменных и функций. Конкретные шаги следующие (браузер):

  • создание страницыглобальный объект GO(Глобальный объект) объект (объект окна).
  • Загрузите первый файл сценария
  • После загрузки скрипта выполните анализ синтаксиса.
  • начать предварительную компиляцию
    • Найдите объявление функции, как атрибут GO, значение присваивается телу функции (объявление функции имеет приоритет)
    • Найдите объявление переменной, в качестве атрибута GO присвойте значение undefined
    • GO/window = {
          //页面加载创建GO同时,创建了document、navigator、screen等等属性,此处省略
          a: undefined,
          c: undefined,
          b: function(y){
              var x = 1;
              console.log('so easy');
          }
      }
  • Коды выполнения интерпретации (функция выполнения до b, часть которой также называетсялексический анализ)
    • Создать АО Активный объект (Активный объект)
    • Найти формальные параметры и объявления переменных, присвоить значения неопределенным
    • Фактическое значение параметра присваивается формальному параметру
    • Найти объявление функции, присвоить значение телу функции
    • Интерпретировать код в функции выполнения

      GO/window = {
          //变量随着执行流得到初始化
          a: 1,
          c: function(){
              //...
          },
          b: function(y){
              var x = 1;
              console.log('so easy');
          }
      }
      
  • После выполнения первого файла сценария загрузите второй файл сценария.
  • После загрузки второго файла выполните синтаксический анализ
  • начать предварительную компиляцию
    • Повторите шаг предварительной компиляции....

Механизм предварительного синтаксического анализа делает подъем переменных (Подъем), что буквально означает, что объявления переменных и функций перемещаются вПереход к началу функции или глобального кода. Давайте проанализируем Xiaolizi, чтобы углубить наше понимание.

console.log(a) // 执行之前,变量提升作为window的属性, 值被设置为undefined
var a = 'hello JS' 

/* JavaScript 仅提升声明,而不提升初始化 */

num = 6;
num++;
var num;
console.log(num) // 变量提升 值为undefined的num赋值为6,再自增 => 7

function hoistFunction() {
    foo();
    function foo() {        
        console.log('running...')    
    }
}
hoistFunction(); // 函数声明提升,可以在函数体之前执行

/* 最后一个栗子 */

alert(a) // 最后的声明为函数声明, 因此a此时为函数体
a(); // 执行 a 函数,输出10
var a = 3; // 3 赋给a
function a() {    
    alert(10)
};
alert(a) // 3
a = 6; // 6赋给a,不是一个函数,故下方执行throw error
a(); // throw error

Примечание. В JS нет настоящей предварительной компиляции, а продвижение var и функции фактически обрабатывается на этапе анализа синтаксиса. А предварительная компиляция JS основана на файле скрипта как на блоке. Файл сценария предварительно компилируется один раз, а не «предварительно компилируется» после компиляции полного текста.


Лучшие практики

Понимание продвижения переменных и продвижения функций может помочь нам продвинуться дальше в JS, но мы не должны использовать эту функцию в разработке, а должны стандартизировать наш код, чтобы добиться удобства сопровождения и удобочитаемости. Будь то переменная или функция, она должна быть объявлена ​​перед использованием. PS: let следует использовать в разработке, чтобы ограничить продвижение переменных.


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

https://developer.mozilla.org/zh-CN/docs/Glossary/Hoisting https://www.cnblogs.com/liuhe688/p/5891273.html http://dmitrysoshnikov.com/notes/note-4-two-words-about-hoisting/ https://segmentfault.com/a/1190000010187653