Оригинальная ссылка:Рисовое путешествие 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).
Затем интерпретатор анализирует оператор построчно.
Если вы попытаетесь получить доступ к переменной на этом этапеvariable
JavaScript бросит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
)неверный. До инициализации переменная находится во временной мертвой зоне и недоступна.
Чтобы поддерживать стабильные объявления переменных, даются следующие рекомендации:
- Объявите, инициализируйте и затем используйте переменную. Процесс правильный и простой для понимания;
- Максимально скройте переменные. Чем меньше переменных выставлено, тем более модульным является код.