Следующий код создает массив функций‑стрелков shooters . По замыслу, каждый стрелок должен выводить свой номер:
function makeArmy() { var shooters = [];
for (var i = 0; i < 10; i++) {
var shooter = function() { // функция‐стрелок alert( i ); // выводит свой номер
};
shooters.push(shooter);
}
return shooters;
}
var army = makeArmy();
army[0](); // стрелок выводит 10, а должен 0 army[5](); // стрелок выводит 10...
// .. все стрелки выводят 10 вместо 0,1,2...9
Почему все стрелки́выводят одно и то же? Поправьте код, чтобы стрелки работали как задумано. Предложите несколько вариантов исправления. Открыть песочницу с тестами для задачи.
К решению
Модули через замыкания
Приём программирования «модуль» имеет громадное количество вариаций. Он немного похож на счётчик, который мы рассматривали ранее, использует аналогичный приём, но на уровне выше.
Его цель – скрыть внутренние детали реализации скрипта. В том числе: временные переменные, константы, вспомогательные мини‑функции и т.п.
Умея работать со страницей, мы могли бы сделать много чего, но так как пока этого не было (скоро научимся), то пусть скрипт просто выводит сообщение:
Файл hello.js
// глобальная переменная нашего скрипта var message = "Привет";
// функция для вывода этой переменной function showMessage() {
alert( message );
}
// выводим сообщение showMessage();
У этого скрипта есть свои внутренние переменные и функции.
В данном случае это message и showMessage .
Предположим, что мы хотели бы распространять этот скрипт в виде библиотеки. Каждый, кто хочет, чтобы посетителям выдавалось «Привет» – может просто подключить этот скрипт. Достаточно скачать и подключить, например, как внешний файл hello.js – и готово.
Если подключить подобный скрипт к странице «как есть», то возможен конфликт с переменными, которые она использует.
То есть, при подключении к такой странице он её «сломает»:
открыть в песочнице
Автор страницы ожидает, что библиотека "hello.js" просто отработает, без побочных эффектов. А она вместе с этим переопределила message в
"Привет" .
Если же убрать скрипт hello.js , то страница будет выводить правильное сообщение.
Зная внутреннее устройство hello.js нам, конечно, понятно, что проблема возникла потому, что переменная message из скрипта hello.js