Оригинальная ссылка:Рисовое путешествие avlutin.com/variables-come…
Поднятие на самом деле является процессом перемещения определений переменных и функций в верхнюю часть области видимости, что обычно происходит в объявлениях переменных.varили объявление функцииfunction fun() {...}.
когдаlet(включая иletимеют такое же заявленное поведениеconstа такжеclass) был представлен ES2015, и многие разработчики, в том числе и я, использовали подъем для описания доступа к переменным. Но, проведя еще несколько поисков по этому вопросу, к моему удивлению, повышение не является описаниемletПравильный термин для инициализации и доступности переменных.
ES2015 даетletПредусмотрены различные и улучшенные механизмы. Это требует более строгой практики объявления переменных (нельзя использовать, пока не определено), поэтому будет более качественный код.
Давайте рассмотрим процесс более подробно.
1. Склонность к ошибкамvarпродвигать
Иногда я вижу странную практику, переменнуюvar varnameи функцияfunction funcName() {...}Объявите в любом месте области видимости:
// var hoisting
num; // => undefined
var num;
num = 10;
num; // => 10
// function hoisting
getPi; // => function getPi() {...}
getPi(); // => 3.14
function getPi() {
return 3.14;
}
numпеременная вvar numЗаявление было доступно ранее, поэтому он считаетсяundefined.
функцияfunction getPi() {...}определяется в конце. Поскольку он поднимается наверх области видимости, функция может быть определенаgetPi()звонили раньше.
Это типичное усиление.
Оказывается, объявление переменной или функции после использования может сбивать с толку. Предположим, вы просматриваете большой файл и вдруг видите необъявленную переменную... как она сюда попала и где она определена?
Конечно, опытный разработчик JavaScript не стал бы писать код таким образом, но очень вероятно, что вы столкнетесь с таким кодом в тысячах репозиториев JavaScript GitHub.
Даже глядя на пример кода, приведенный выше, трудно понять поток объявлений в коде.
Естественно, сначала объявляется или описывается неизвестное слово, и только потом оно используется для написания словосочетания.letСледуя этому подходу, рекомендуется использовать переменные.
2. Исследуйте нижний слой: жизненный цикл переменных
Когда движок обращается к переменным, их жизненный цикл включает следующие этапы:
- Фаза объявления: зарегистрируйте переменную в области видимости
- Фаза инициализации: выделение памяти и создание привязок к переменным в области видимости. На этом этапе переменная автоматически инициализируется
undefined - Фаза присваивания: присвоение значения уже инициализированной переменной
Переменная, прошедшая стадию объявления, но не дошедшая до стадии инициализации, находится в неопределенном состоянии.
Обратите внимание, что фаза объявления и объявление переменной в целом — это разные термины, зависящие от срока жизни переменной. Вкратце, механизм обрабатывает объявления переменных в три этапа: этап объявления, этап инициализации и этап назначения.
3.varпеременный жизненный цикл
Знакомые с фазами жизненного цикла, мы используем их для описания того, как работает движок.varПеременная.
varФункция объявленной переменной. Эта переменная проходит фазу объявления и фазу инициализации (первый шаг) перед выполнением любого оператора.
var variableПоложение объявления в области действия функции не влияет на этапы объявления и инициализации.
После объявления и инициализации, но перед фазой присваивания значение переменнойundefinedи могут быть доступны для использования.
На этапе назначения,variable = 'value', переменная получает свое начальное значение (шаг 2).
Строго говоря, концепция подъема заключается в объявлении и инициализации переменных в верхней части области видимости функции. Между фазами объявления и инициализации нет разрыва.
Давайте изучим пример. Следующий код создаетvarПеременная функция:
function multiplyByTen(number) {
console.log(ten); // => undefined
var ten;
ten = 10;
console.log(ten); // => 10
return number * ten;
}
multiplyByTen(4); // => 40
Когда JavaScript начинает выполнятьсяmultipleByTen(4), оно вошлоmultipleByTenОбласть действия функции, перед первым оператором, переменнаяtenФаза объявления и инициализации завершена. так позвониconsole.log(ten)распечатаетundefined.
утверждениеten = 10Присваивается начальное значение. После выделения,console.log(ten)10 правильно вывод.
4. Жизненный цикл декларации функции
Предположим, оператор объявления функцииfunction funName() {...}, что проще.
funcName()Может вызываться в любом месте области видимости, независимо от того, где объявлен оператор (даже в конце).
В следующем примере кода демонстрируется подъем функции:
function sumArray(array) {
return array.reduce(sum);
function sum(a, b) {
return a + b;
}
}
sumArray([5, 10, 8]); // => 23
Когда JavaScript вызываетsumArray([5, 10, 8]), оно вошлоsumArrayобъем функции. Внутри области, прежде чем все операторы будут выполнены,sumПрошел три этапа: объявление, инициализация, присваивание.
Сюда,array.reduce(sum)даже в объявлении заявлениеfunction sum(a, b) {...}использовался раньшеsum.
5.letпеременный жизненный цикл
letКак обрабатываются переменные иvarразные. Основное отличие состоит в том, что этапы объявления и инициализации разделены.
let variableутверждение. Переменная сразу проходит фазу объявления, регистрируя свое имя в области видимости (шаг 1).
Затем интерпретатор анализирует оператор построчно.
Если вы попытаетесь получить доступ к переменной на этом этапеvariableJavaScript броситReferenceError: variable is not defined. Потому что состояние переменной не определено,variableво временной мертвой зоне.
когда придет переводчикlet variableоператор, фаза инициализации проходит (шаг 2). Теперь состояние переменной определено, и доступ к ней дастundefined.
Переменная выходит из временной зоны нечувствительности.
Позже, когда оператор присваиванияvariable = 'value'появляется, пройдя фазу назначения (шаг 3).
Если JavaScript встречаетlet variable = 'value', то инициализация и присваивание будут происходить в этом единственном операторе.
Давайте посмотрим на пример. используется в области блокаletобъявить переменнуюvariable:
let condition = true;
// console.log(number); // => Throws ReferenceError
let number;
console.log(number); // => undefined
number = 5;
console.log(number); // => 5
}
когда входит javascriptif (condition) {...}При блочной области видимостиnumberСразу прошел этап декларирования.
потому чтоnumberнаходится в неопределенном состоянии, во временной мертвой зоне, попытка доступа к этой переменной выдаетReferenceError: number is not defined.
Позднее приговорlet numberИнициализация завершена. Теперь переменная доступна, но ее значение равноundefined.
оператор присваиванияnumber = 5Разумеется, этап задания завершен.
constа такжеclassтип иletимеют одинаковое время жизни, за исключением того, что присвоение может произойти только один раз.
5.1 Зачем подниматьletнедействителен при жизни
如上所述,提升就是变量在作用域顶部进行声明和初始化。 ноletЖизненный цикл объявит и инициализирует два этапа отделен. Разделение позволяет восхождение на срок неэффективной.
Промежуток между двумя этапами создает временную мертвую зону, где переменные недоступны.
в научно-фантастическом стилеletКрах термина вознесение создает временную мертвую зону в течение жизненного цикла.
6. Заключение
Не стесняйтесь использоватьvarОбъявление переменных подвержено ошибкам. На основе этого урока ES2015 создалlet. Он использует улучшенный алгоритм объявления переменных и область видимости на уровне блоков.
Благодаря разделению фаз объявления и определения, подъем дляletобъявленные переменные (включаяconstа такжеclass)неверный. До инициализации переменная находится во временной мертвой зоне и недоступна.
Чтобы поддерживать стабильные объявления переменных, даются следующие рекомендации:
- Объявите, инициализируйте и затем используйте переменную. Процесс правильный и простой для понимания;
- Максимально скройте переменные. Чем меньше переменных выставлено, тем более модульным является код.