О вызове функции в цикле
Задача следующая: вызывать функцию в цикле, в качестве одного из аргументов принимая переменную цикла.
Тут не совсем всё так просто, как кажется на первый взгляд. Казалось бы, очевидно:
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);
}
Для каждого из ответов мы можем дать свой обработчик событий.