Одной из общих проблем, с которой сталкиваются начинающие разработчики на JavaScript, является понимание работы замыканий в циклах. Давайте рассмотрим типичный пример, который демонстрирует эту проблему.
var funcs = []; for (var i = 0; i < 3; i++) { funcs[i] = function() { console.log("My value: " + i); }; } for (var j = 0; j < 3; j++) { funcs[j](); }
Ожидается, что код выше выведет числа от 0 до 2, но на самом деле он выводит число 3 три раза. Это происходит потому, что функции в JavaScript образуют замыкания и имеют доступ к переменным из внешней области видимости в момент их вызова, а не в момент их создания.
Замыкание — это функция, которая имеет доступ к переменным из внешней (родительской) области видимости, даже после того, как родительская функция завершила свою работу. В данном случае, все функции в массиве funcs
имеют доступ к одной и той же переменной i
.
Когда цикл for
выполняется, переменная i
увеличивается на единицу на каждой итерации. Когда цикл завершается, i
становится равным 3. Поэтому, когда функции в funcs
вызываются, они все ссылаются на одно и то же значение i
, которое теперь равно 3.
Чтобы решить эту проблему, можно использовать еще одно замыкание, чтобы «захватить» текущее значение i
на каждой итерации цикла. Вот как это можно сделать:
var funcs = []; for (var i = 0; i < 3; i++) { funcs[i] = (function(value) { return function() { console.log("My value: " + value); } })(i); } for (var j = 0; j < 3; j++) { funcs[j](); }
В этом коде на каждой итерации цикла создается новая анонимная функция, которая принимает текущее значение i
в качестве аргумента. Затем эта функция возвращает новую функцию, которая выводит значение этого аргумента. Таким образом, каждая функция в funcs
теперь ссылается на свое собственное значение, которое было «захвачено» на момент создания этой функции.
Это решение позволяет каждой функции в funcs
иметь свое собственное значение i
, что дает ожидаемый результат.
Добавить комментарий