О вызове функции в цикле

Задача следующая: вызывать функцию в цикле, в качестве одного из аргументов принимая переменную цикла.
Тут не совсем всё так просто, как кажется на первый взгляд. Казалось бы, очевидно:

for (var i=0; i< 5; i++) {
    (function request(i){ 
	console.log(i)			
    }(i));
}

Однако, если выполнение функции нелинейно, то произойдёт облом:

for (var i=0; i< 5; i++) {
    $.get('/', function(data){
	console.log(i)
    })
}

Не сохранён контекст выполнения функции.

Первый способ вызвать функцию с контекстом: назвать её и вызвать явно. Функции в JS являются объектами, и в таком виде контекст будет передан во время вызова, то есть на каждом шаге цикла со своим i:

for (var i=0; i< 5; i++) {
    (function request(i){ 
	$.get('/', function(data){
	    console.log(i)
	})			
    }(i));
}

Или вот так, явно:

for (var i=0; i< 5; i++) {
    var obj = {		
        request : function(num){$.get('/', function(data){
	    console.log(num)
        })}		
    };
    obj.request(i);	   
}

Второй способ – использовать встроенный метод .call() объекта Function:

for (var i=0; i< 5; i++) {
    (function request(i){
        $.get('/', function(data){
	    console.log(i)
	})		
    }).call(this, i);
}

Второй способ более гибкий, т.к. позволяет передавать нужный нам this:

var cars = [
  { auto: 'BMW', model: 'E34' },
  { auto: 'Mercedes', model: 'W124' }
];
for (var i = 0; i < cars.length; i++) {
  (function(i) {  
      console.log(this.auto + ' ' + this.model);   
  }).call(cars[i], i);
}

Соответственно, не нужно тащить весь список аргументов, достаточно передать нужный контекст.
Таким образом, наш первый пример может выглядеть так:

var binds = [
    {       
	doSomeFunc : function (i) {
	    console.log(i + i);
	}		
    },
    {         
	doSomeFunc : function(i) {
	    console.log(i*3);
	}
    }	
];
for (var i=0; i< 2; i++) {
    (function (i){   
        var self = this;
        $.get('/', function(data){           
			self.doSomeFunc(i);			
		})		
    }).call(binds[i], i);
}

Для каждого из ответов мы можем дать свой обработчик событий.

Теги: