предисловие
Переменные повсюду в нашей повседневной работе. Более глубокое понимание этого может поднять ваш уровень 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