Замыкания в JavaScript

Счётчик на замыкании

var getId = function(){
   var counter = 1;
   return function(){
      return counter++;
   } 
}
var res = getId();
console.log(res());  // 1
console.log(res());  // 2

Каждый раз вызывая getId(), будем получать увеличенное на 1 значение счётчика. Внутренняя переменная, отвечающая за счётчик, при этом недоступна извне: мы не сбросим его случайно или намеренно.

Буффер строк

Нужна функция, суммирующая входящие параметры в строке, с методом clear очистки содержимого. Реализация:

function makeBuffer() {
   var res = "";
   function buffer(newString){
      if (newString) res += newString;
      return res;      
   }
   buffer.clear = function(){res = ""};
   return buffer;
}
var buffer = makeBuffer();
var x = buffer(0);
x = buffer(1);
x = buffer(2);
console.log(x);  // 12
buffer.clear();
x = buffer();  
console.log(x);  // пустая строка
x = buffer(3);
console.log(x);  // 3

Задача про стрелков

Дан код. По логике, он должен выводить последовательно номера стрелков, однако всегда выводит 10:

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...

Причина ошибки ясна. Ниже два решения с замыканиями, без использования глобальных переменных или свойств объекта:

function makeArmy() {
   var shooters = [];
   for (var i = 0; i < 10; i++) {
      var shooter = (function(x) { 
         return function(){ alert( x )}    
      })(i);
      shooters.push(shooter);
   }
   return shooters;
}
var army = makeArmy();
 
army[0]();  // 0
army[5]();  // 5
 
 
 
function makeArmy() {
   var shooters = [];
   for (var i = 0; i < 10; i++) (function(x){
      var shooter = function() { 
         alert( x ); 
      };
      shooters.push(shooter);
   })(i)
   return shooters;
}
 
var army = makeArmy();
 
army[0]();  // 0
army[5]();  // 5
Теги: