Вынужденный отказ закрытия (использование закрытия)

JavaScript
Вынужденный отказ закрытия (использование закрытия)

Добавить Автора

Оригинальная постоянная ссылка: 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.

конец:На самом деле, в этот момент можно в принципе понять, что проблема второго плана на самом деле闭包作用域链Проблема в том, что при формировании замыкания замыкание включает作用域链будет спасен. Если вы действительно понимаете замыкания, вы никогда не столкнетесь с такими проблемами, как моя, что является уроком для меня. Я надеюсь, что вы можете указать на плохое письмо.Ниже приведена ссылка на статью для справки.

(Если вышеуказанный контент вызывает у вас дискомфорт, вы можете обратиться кБлог Сае Ю)

Справочная статья:

Закрытие MDN

Углубленный контекст выполнения JavaScript

Глубокие замыкания JavaScript

Смотрите больше сообщений в блоге:

Персональные самородки Больше ссылок на статьи;

Ссылки на другие статьи в проекте публикации в блоге GitHub;