Оригинальная постоянная ссылка: https://github.com/AttemptWeb/Record…
Смущенный, я столкнулся с проблемой закрытия, а затем дал неправильный ответ и не смог притвориться. Раньше я думал, что полностью понял закрытие, но теперь я обнаружил, что это не так, и быстро перевернул книгу, чтобы найти ответ- инж.
Посмотрите на код ниже, импортируйте функцию в массив в цикле, надеюсь, она сможет напечатать**0,1,2** :
function func() {
var arr = [];
for(var i = 0;i<3;i++){
arr.push(()=> {
console.log(i);
})
}
return arr
}
var result = func();
result.forEach((item)=> {
item();
})
<!-- 打印信息 三个3 -->
// 3
Выясняется, что печатаются все 3, причина в том, что в анонимной функции**i**имеют один и тот же лексический объем. Когда анонимная функция вызывается с массивом переменных,varОбъявленная переменная не имеет области блока,**i**Значение уже указывает на**for**цикл**i**последний пункт из .
решить вышеуказанные проблемы
использовать**let**или**闭包**Вышеупомянутая проблема может быть решена, код решения выглядит следующим образом:
<!-- 方案一 -->
// 使用let 声明变量
function func() {
var arr = [];
for(let i = 0;i<3;i++){
arr.push(()=> {
console.log(i);
})
}
return arr
}
var result = func();
result.forEach((item)=> {
item();
})
<!-- 方案二 -->
// 使用闭包
function func() {
var arr = [];
for(var i = 0;i<3;i++){
(function(){
arr.push(()=> {
console.log(i);
})
})()
}
return arr
}
var result = func();
result.forEach((item)=> {
item();
})
Думал, что проблема решена, но других проблем не возникло! Вы можете запустить приведенную выше схему 1 и схему 2, вы обнаружите, что результат схемы 2 распечатываетсятри 3,ВТ? не должен печатать0、1、2, Как не?
Закрытие области видимости
Конечно, в первой схеме нет проблем, используйте**let**Решить проблему масштаба. Во втором варианте используйте**闭包**разрешающая переменная**i**проблемы с обзором, но кажется**闭包**не удалось.
во втором вариантеРоль закрытия состоит в том, чтобы приватизировать переменные, сохранить цепочку областей закрытия, переменныеiне уничтожен. Если вы не знаете о области закрытия, вы можете проверить этоСае Юиз Углубленный контекст выполнения JavaScript иГлубокие замыкания JavaScript. Результат на втором плане не тот, что мы хотим.Причина в том, что я闭包作用域Вызвано непониманием.
<!-- 方案三 -->
function func() {
var arr = [];
for(var i = 0;i<3;i++){
(function(i){
arr.push(()=> {
console.log(i);
})
})(i) // 加了参数i
}
return arr
}
var result = func();
result.forEach((item)=> {
item();
})
Вышеупомянутое решение, будет **i**Добавление его к параметру анонимной функции решает проблему второго решения.
Давайте поговорим о том, что происходит, **почемубудетi**Добавление к параметру анонимной функции решает указанную выше проблему.?
为了方便描述,我将 自运行的匿名函数 简称为 **fn1**, 而arr中的匿名函数 简称为 **fn2**. Конечно, три функции в arr — это три разные функции fn2.
цепочка области действия функции
fn2函数作用域链 : {
arr中的匿名函数fn2函数变量和参数 , fn1函数变量&&参数 , func函数变量&&参数 , 全局作用域变量
}
при звонкеfuncфункция, функцияfn1самоходный, переменныйarrвводят триfn2функция, в то время какarrодеялоreturnпублично заявить. сформировался в это время闭包作用域链.
в массивеfn2Функция запускается и продолжает искать i,fn1функция иfn2не существует в функцииi, пока не нашелfuncфункциональная переменная i, в настоящее время из-заiдаvarЗаявлено, что нет блочной области видимости, триfn2совместное использование функцийi. (На самом деле, это место немного повторяется из первого объяснения, но новая вещь, которая появляется здесь, может быть闭包作用域链).
После обычного вызова функции**作用域链**уничтожен,но когда есть**闭包**когда соответствующие**作用域链**будет сохранен.arrсерединаfn2Объем функции в основном формирует作用域链,作用域链是单向的,内部向外部查找,由下向上查找.作用域链中会保存局部变量、全局变量、函数参数.
Сравните вариант 2 и вариант 3.
// 方案二
function func() {
var arr = [];
for(var i = 0;i<3;i++){
(function(){
arr.push(()=> {
console.log(i);
})
})()
}
return arr
}
var result = func();
result.forEach((item)=> {
item();
})
Посмотрим сейчасВариант 2: при обходе вызова результатаarrсерединаfn2Сначала функция найдет себя函数作用域, если i не существует, то продолжаем поиск вверх и находимfuncпод функцией变量i,будетiраспечатывает, но в это времяfuncв функции变量iуже равно 3, так какforцикл три раза,arrесть триfn2函数, как и выше, поэтому 3 напечатано три раза.
// 方案三
function func() {
var arr = [];
for(var i = 0;i<3;i++){
(function(i){
arr.push(()=> {
console.log(i);
})
})(i)
}
return arr
}
var result = func();
result.forEach((item)=> {
item();
})
пока втретье решение: при обходе вызова результатаarrсерединаfn2Сначала функция найдет себя函数作用域,не существуетiЗатем продолжайте искать и найдитеfn1Параметры в функцииi, распечатайте I. Поскольку есть три анонимных функции, параметры функции0、1、2.
конец:На самом деле, в этот момент можно в принципе понять, что проблема второго плана на самом деле闭包作用域链Проблема в том, что при формировании замыкания замыкание включает作用域链будет спасен. Если вы действительно понимаете замыкания, вы никогда не столкнетесь с такими проблемами, как моя, что является уроком для меня. Я надеюсь, что вы можете указать на плохое письмо.Ниже приведена ссылка на статью для справки.
(Если вышеуказанный контент вызывает у вас дискомфорт, вы можете обратиться кБлог Сае Ю)
Справочная статья:
Углубленный контекст выполнения JavaScript
Смотрите больше сообщений в блоге:
Персональные самородки Больше ссылок на статьи;
Ссылки на другие статьи в проекте публикации в блоге GitHub;