Друг мой и я в настоящее время обсуждаем, что такое закрытие в JS, а что нет. Мы просто хотим убедиться, что мы действительно понимаем это правильно.
Возьмем этот пример. У нас есть цикл подсчета и вы хотите напечатать переменную счетчика на консоли. Поэтому мы используем setTimeout
и замыкания, чтобы зафиксировать значение переменной счетчика, чтобы убедиться, что оно не будет печатать в N раз значение N.
Неправильное решение без закрытий или что-нибудь рядом с закрытием будет:
for(var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
который, разумеется, напечатает в 10 раз значение i
после цикла, а именно 10.
Таким образом, его попытка заключалась в следующем:
for(var i = 0; i < 10; i++) {
(function(){
var i2 = i;
setTimeout(function(){
console.log(i2);
}, 1000)
})();
}
печать от 0 до 9, как ожидалось.
Я сказал ему, что он не использует закрытие для захвата i
, но он настаивает на том, что он есть. Я доказал, что он не использует закрытия, поместив тело for loop в другой setTimeout
(передав свою анонимную функцию на setTimeout
), снова напечатав 10 раз 10. То же самое происходит, если я сохраняю его функцию в var
и выполняю ее после цикла, также печатаю 10 раз 10. Поэтому мой аргумент состоит в том, что он действительно не фиксирует значение i
, делая его версию не закрытием.
Моя попытка:
for(var i = 0; i < 10; i++) {
setTimeout((function(i2){
return function() {
console.log(i2);
}
})(i), 1000);
}
Итак, я фиксирую i
(названный i2
в закрытии), но теперь я возвращаю другую функцию и передаю ее. В моем случае функция, переданная в setTimeout, действительно захватывает i
.
Теперь кто использует закрытие, а кто нет?
Обратите внимание, что оба решения печатают от 0 до 9 на консоли, поэтому они решают исходную проблему, но мы хотим понять, какое из этих двух решений использует закрытие для выполнения этого.