предисловие
Прежде чем изучать замыкания, мы должны сначала понять область видимости и лексическую область видимости. Как только вы освоитесь, вам потребуется всего один шаг, чтобы наконец понять замыкания.
объем
определение
В JavaScript доступность переменных управляется областью видимости. Области создаются функциями или блоками кода. Переменная может использоваться только внутри функции или блока кода, в котором она определена. вне пределов досягаемости
в этом примере
countпеременная принадлежитfooОбласть действия, создаваемая функцией, в пределах которой она доступна. Если доступ извнеcountЭто вызовет ошибку и будет выполняться при нормальных обстоятельствах.fooПосле функции прицел, которым он владеет, будет активно выпущен и уничтожен.
Изоляция переменных
Мы можем понимать область действия как космическую стратегию, каждая функция имеет свою собственную область видимости, которая изолирует переменные и контролирует доступность переменных, поэтому разные области видимости могут иметь переменные с одинаковыми именами без конфликта.
Соответственно
foo()а такжеbar()определение области действияcountПеременные не сталкиваются.
вложение области видимости
мы можем поставить
innerFunc()вложен во внешнюю функциюouterFunc(), во внешней областиouterVarПеременные доступны во внутренних областях.
резюме
- Области могут быть вложенными
- Доступ к переменным во внешней области можно получить во внутренней области.
- Если он не найден во внешней области, он в конечном итоге перейдет в глобальную область, чтобы найти его, от внутреннего к внешнему слою, чтобы сформировать
作用域链
Расширение:Мы называем поведением, когда внутренняя область может получить доступ к внешней области, но внешняя не может получить доступ к внутренней области.作用域继承, глобальную область можно сравнить с большим домом со множеством уровней маленьких комнат (область функции или область блока), каждая со своим ключом 🔑. К внешнему можно получить доступ изнутри, но к внутреннему нельзя получить доступ снаружи и нельзя получить доступ друг от друга
лексический объем
В JavaScript используется лексическая область видимости. Лексическая область видимости (статическая область видимости) — это область, определенная на лексическом этапе. Она называется лексической (или статической), потому что движок (во время лексикализации) просматривает только исходный код JavaScript. область определяется без выполнения кода, поэтому область сохраняется при обработке кода лексером.
const myGlobal = 0;
function func() {
const myVar = 1;
console.log(myGlobal); // "0"
function innerOfFunc() {
const myInnerVar = 2;
console.log(myVar, myGlobal); // "1 0"
function innerOfInnerOfFunc() {
console.log(myInnerVar, myVar, myGlobal); // "2 1 0"
}
innerOfInnerOfFunc();
}
innerOfFunc();
}
func();
-
innerofinnerOfffuncunc () - это лексическая область, включенная в действие (), Func () глобальный объем и состав. В innerofinnerOfffuncunc () вы можете получить доступ к переменной Myinnervar, Myvar и MyGlobal.
-
Лексический объем Innerfunceunc () состоит из Func () и глобальной массы. В InneroffUnc () доступны переменные Myvar и MyGlobal.
-
Лексическая область видимости функции func() включает только глобальную область видимости. В func() можно получить доступ к переменной myGlobal.
проиллюстрировать:Лексическая область видимости означает, что доступность переменной определяется положением переменной во вложенной области в исходном коде, а доступ к переменной во внутренней области можно получить во внешней области. Такая структура области обеспечивает достаточную информацию о местоположении для выполнения механизма, и механизм может найти соответствующие переменные в соответствии с правилом поиска с повышением уровня.
Простой пример:
var value = 1;
function foo() {
console.log(value);
}
function bar() {
var value = 2;
foo();
}
bar(); // 1
Выходной результат в js равен 1, что является эффектом лексической области видимости, здесьbar()передачаfoo()Времяfoo()не вbar()Он ищет переменную значения в , но сначала запрашивает свою собственную область, а затем напрямую запрашивает глобальную в соответствии с механизмом поиска цепочки областей. (поиск по области останавливается, когда он находит первый соответствующий идентификатор)
расширение: eval(),withМожет «обманывать» лексические области видимости и замедлять работу кода, не используйте их
Чтобы было понятно, на самом деле javascript не имеет динамической области видимости, у него есть только лексическая область видимости, простая и понятная, но этот механизм чем-то похож на динамическую область видимости.
Закрытие
Ранее мы видели, что лексическая область видимости обеспечивает статический доступ к переменным во внешней области. В шаге от закрытия!
Давайте рассмотрим этот пример:
function outerFunc() {
let outerVar = 'I am outside!';
function innerFunc() {
console.log(outerVar); // "I am outside!"
}
innerFunc();
}
outerFunc();
Теперь мы знаем, что вinnerFunc()Доступ к переменным с областью видимости можно получить из лексической области видимости.outerVar,здесьinnerFunc()Вызов происходит в своей лексической области (outerFunc()объем).
ПучокinnerFunc()Модифицированный до его лексического объема (outerFunc()снаружи) звоните.innerFunc()также доступouterVar?
Подправим фрагмент кода:
function outerFunc() {
let outerVar = 'I am outside!';
function innerFunc() {
console.log(outerVar); // "I am outside!"
}
return innerFunc;
}
const myInnerFunc = outerFunc();
myInnerFunc();
СейчасinnerFunc()Выполняется вне своего лексического объема, ноinnerFunc()все еще доступным из его лексического объемаouterVar, даже если выполняется за пределами лексической области. то естьinnerFunc()Захват (или запоминание) переменной из ее лексической области видимостиouterVar.
другими словами,innerFunc()является замыканием, потому что оно захватывает переменную в лексической области видимостиouterVar.
Обычно, когдаouterFuncПосле выполнения функции ее область видимости будет уничтожена, а затем сборщик мусора освободит это место в памяти. Закрытия потрясающиеouterFuncСфера сохранилась,innerFuncОн по-прежнему содержит ссылку на область действия, и эта ссылка является закрытием.На этом мы завершили последний шаг в понимании замыканий:
Замыкание — это функция, которая запоминает переменные с того места, где она определена, образуя приватную область видимости, защищая приватные переменные внутри от вмешательства извне, помимо защиты приватных переменных, она еще может хранить какой-то контент, вне зависимости от его будущего, где находится выполняется, поэтому независимо от того, как внутренняя функция передается из лексической области видимости, в которой она находится, она будет содержать ссылку на исходную область видимости, и замыкание будет использоваться везде, где функция выполняется.
Эмпирическое правило для определения замыканий: если вы видите внешнюю переменную в функции (не определенную внутри функции), то функция, скорее всего, является замыканием, потому что внешняя переменная захвачена.
Как видно из предыдущего фрагмента кодаinnerFunc()внешние переменные в замыканияхouterVarОтouterFunc()захват с прицелом.
Чтобы наблюдать за значением переменной среды, записанной в замыкании, вы можете увидеть его из консоли браузера, как в приведенном выше примере, если вы добавите точку останова в консоль браузера и понаблюдаете, вы увидите следующее изображение:можно увидеть на рисунке
innerFuncиз作用域(Scope)Будет имяClosoure(闭包), так вы можете наблюдать значение переменных среды в замыкании.
резюме
Когда функция вызывается за пределами лексической области, когда она определена, замыкание может ограничить доступ к лексической области, когда функция определена.
расширять: С точки зрения непрофессионала, замыкание — это определение функции внутри функции. Эта внутренняя функция всегда поддерживает доступ к области действия внешней функции (маленькая комната всегда может иметь доступ к большому дому).
Роль замыканий
- Доступ к переменным внутри других функций
- Защитите переменные от восстановления с помощью механизма восстановления памяти.
- Избегайте загрязнения глобальных переменных Облегчайте локальные переменные контекста вызова Улучшайте инкапсуляцию
Например в vue2
definePropertyправильноdepСсылки на экземпляры, давайте продолжим с некоторыми примерами того, почему замыкания полезны.
Пример закрытия
обработчик события
let countClicked = 0;
myButton.addEventListener('click', function handleClick() {
countClicked++;
myText.innerText = `You clicked ${countClicked} times`;
});
В этом случае текст будет обновляться, чтобы показать количество кликов. Когда кнопка нажата,handleClick()Выполняется где-то внутри кода DOM вне определения.
Но как закрытие,handleClick()Захват из лексической областиcountClicked, и обновлять его, когда происходит щелчок. важнее,myTextтоже попал в плен.
Перезвоните
Захват переменных из лексической области полезен в обратных вызовах.
function foo(message, time) {
setTimeout(function callback() {
console.log(message); // Hello, World!
}, 1000);
}
foo('Hello, World!', 1000);
Зачемcallback()является замыканием, потому что оно захватывает переменнуюmessage.
Классические сценарии использования замыканий
Существует также довольно классический сценарий для замыканий, который часто упоминается в интервью, — это функции в циклах for.
var arr = [];
for(var i = 0; i< 5; i++){
arr[i] = function(){
return i;
}
}
arr[0](); // 5
В этой проблеме я переменная передается. Когда конец петли я стал 5 а. Так что вывод ARR0 - 5. Чтобы решить проблему, при необходимости в определениях анонимных функций ARR [I], нам нужно запомнить значение i, но не всегда может меняться. С идеей замыкания состоит в том, чтобы я в каждой итерации создал личную область, сохранить значение нынешнего I в роли частного домена, каждая область не зависит от влияния, он избегает делиться I, а я есть последние 5 к проблемам. Кодовое шоу, как показано ниже.
var arr = [];
for(var i = 0; i< 5; i++){
arr[i] = (function(i){
return function(){
return i;
}
})(i)
}
arr[0](); // 0
Окончательное решение, которое является знанием ES6, потому что до того, как в JS не было концепции области на уровне блоков, для ES6 там, пусть объявление переменной может лучше решить проблему.
var arr = [];
for (let i = 0; i < 5; i++) {
arr[i] = function () {
return i;
};
}
arr[0](); // 0
Резюме 🥇
Область видимости определяет доступность переменных в JavaScript. Он в основном включает область действия функции и область действия блока.
Лексическая область видимости позволяет областям функций статически обращаться к переменным из внешней области.
Наконец, замыкания — это функции, которые захватывают переменные из их лексической области видимости. Проще говоря, замыкание запоминает переменные из того места, где оно было определено, независимо от того, где оно выполняется.
Замыкания захватывают обработчики событий, переменные в обратных вызовах. Они используются в функциональном программировании.
расширение 🏆
Если эта статья окажется для вас полезной, вы можете ознакомиться с другими моими статьями ❤️:
👍5 шаблонов дизайна, которые вы должны знать о веб-разработке 🍊
👍10 простых приемов, которые сделают ваш код vue.js более элегантным 🍊
👍Говоря о процессе рукопожатия протокола SSL🍊
👍Разблокируйте новые позы этого, применяйте, звоните, связывайте 🍊