Прежде чем формально изучать замыкания, убедитесь, что вы правы.лексический объемВы уже хорошо знакомы с ним. Если вы не знакомы с лексической областью видимости, вы можете сначала прочитать его:
предисловие
Теперь идите на собеседование на позицию фронтенд-разработчика.Если вы также фронтенд для интервьюера, и вы не слишком водянисты, есть большая вероятность, что вас спросят о замыканиях в JavaScript. Потому что знание этого замыкания действительно важно, и его очень сложно освоить.
что такое закрытие
Что такое закрытие, вы можете найти много ответов....
«Продвинутое программирование на JavaScript» описывает это следующим образом:
Замыкание — это функция, которая имеет доступ к переменной в области видимости другой функции;
Полное руководство по JavaScript описывает это следующим образом:
Технически все функции JavaScript являются замыканиями: все они являются объектами, и все они связаны с цепочкой областей видимости.
«JavaScript, которого вы не знаете» описывает это так:
Закрытие происходит, когда функция может запомнить и получить доступ к лексической области, в которой она находится, даже если функция выполняется за пределами текущей лексической области.
С чем я согласен больше всего, так это с описанием в «JavaScript, которого вы не знаете». Хотя предыдущие два утверждения не являются ошибочными, замыкания должны быть естественным результатом написания кода, основанного на лексической области видимости. Это феномен! Вам не нужно создавать их специально, чтобы воспользоваться преимуществами замыканий, потому что замыкания можно увидеть повсюду в вашем коде, но вы не знаете, что кусок кода, который вы написали в то время, действительно генерирует замыкания.
Объясните закрытие
Как указано выше,Закрытие происходит, когда функция может запомнить и получить доступ к лексической области, в которой она находится, даже если функция выполняется за пределами текущей лексической области..
увидеть кусок кода
function fn1() {
var name = 'iceman';
function fn2() {
console.log(name);
}
fn2();
}
fn1();
Если это соответствует "Продвинутому программированию на JavaScript" и "Полном руководстве по JavaScript", приведенный выше код сгенерировал замыкания. fn2 обращается к переменной fn1, которая удовлетворяет условию «функция, которая имеет доступ к переменным в области действия другой функции», а сама fn2 является функцией, поэтому она удовлетворяет условию «все функции JavaScript являются замыканиями».
Это действительно замыкание, но замыкание, определенное таким образом, не очень легко наблюдать.
Посмотрите на другой фрагмент кода:
function fn1() {
var name = 'iceman';
function fn2() {
console.log(name);
}
return fn2;
}
var fn3 = fn1();
fn3();
Это ясно показывает закрытие:
-
Лексическая область fn2 может получить доступ к области действия fn1.
-
вернуть fn2 как значение
-
После выполнения fn1 назначьте ссылку fn2 на fn3.
-
Выполнить fn3, вывести имя переменной
Мы знаем отношение по ссылке, fn3 — это сама функция fn2. Выполнение fn3 может нормально выводить имя, что означает, что fn2 может запомнить и получить доступ к лексической области, в которой оно находится, а работа функции fn2 все еще находится за пределами текущей лексической области.
Обычно при выполнении функции fn1 ее область действия уничтожается, а затем сборщик мусора освобождает это пространство памяти. Замыкание волшебным образом выживает за пределами fn1,fn2 по-прежнему содержит ссылку на область действия, которая является закрытием.
Суммировать:Функция вызывается за пределами лексической области во время определения, и замыкание может ограничить доступ функции к лексической области во время определения..
Примечание: Передача значения функции может осуществляться другими способами, и значение не обязательно должно возвращаться в функцию, например, вы можете использовать функцию обратного вызова:
function fn1() {
var name = 'iceman';
function fn2() {
console.log(name);
}
fn3(fn2);
}
function fn3(fn) {
fn();
}
fn1();
В этом примере внутренняя функция fn2 передается в fn3, и когда она запускается в fn3, она может получить доступ к переменной name.
Таким образом, независимо от того, каким образом внутренняя функция передается из лексической области видимости, она по-прежнему содержит ссылку на исходную область видимости, а замыкание используется везде, где выполняется функция.
Объясните закрытие снова
Приведенный выше пример заставит людей почувствовать себя немного академичными, но замыкания — это не просто бесполезная концепция.В написанном вами коде должны быть замыкания, например код, подобный следующему:
function waitSomeTime(msg, time) {
setTimeout(function () {
console.log(msg)
}, time);
}
waitSomeTime('hello', 1000);
В таймере есть анонимная функция, анонимная функция имеет замыкание, охватывающее область действия функции waitSomeTime, поэтому через 1 секунду анонимная функция может выводить msg.
Другой классический пример — проблема использования таймера для задержки печати в цикле for:
for (var i = 1; i <= 10; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}
В этом коде мы ожидаем, что он выведет 1~10, но он выводит 11 10 раз. Это связано с тем, что при выполнении анонимной функции в setTimeout цикл for уже завершился Условием окончания цикла for является то, что i больше 10, поэтому, конечно, он выводит 11 10 раз.
Причина: i объявлен в глобальной области видимости, и анонимная функция в таймере также выполняется в глобальной области видимости, которая, конечно же, каждый раз выводит 11.
Причина известна, а решение простое: мы можем заставить i генерировать приватную область видимости на каждой итерации и сохранять текущее значение i в этой приватной области видимости.
for (var i = 1; i <= 10; i++) {
(function () {
var j = i;
setTimeout(function () {
console.log(j);
}, 1000);
})();
}
Это оправдало наши ожидания.Давайте изменим его более элегантным способом, передавая i каждой итерации в качестве фактического параметра самовыполняющейся функции и используя переменную для получения его в самовыполняющейся функции:
for (var i = 1; i <= 10; i++) {
(function (j) {
setTimeout(function () {
console.log(j);
}, 1000);
})(i);
}
Применение затворов
Типичным применением замыкания является определение модуля, мы выставляем функцию операции наружу, а детали скрыты внутри модуля:
function module() {
var arr = [];
function add(val) {
if (typeof val == 'number') {
arr.push(val);
}
}
function get(index) {
if (index < arr.length) {
return arr[index]
} else {
return null;
}
}
return {
add: add,
get: get
}
}
var mod1 = module();
mod1.add(1);
mod1.add(2);
mod1.add('xxx');
console.log(mod1.get(2));
Примечание
О замыканиях можно еще много говорить, здесь мы сначала объясним более базовые концепции, а затем будет более захватывающий контент.
обращать внимание
Вы можете обратить внимание на мой паблик: icemanFE и продолжать обновлять технические статьи!