Это одна из самых хитрых частей javascript scope imo.
Когда вы находитесь внутри цикла и создаете анонимные функции на основе индекса из цикла, вам нужно выполнить что-то вроде bind , curry ,или анонимные функции, выполняемые самостоятельно , чтобы убедиться, что вы вводите правильное значение.
Концепция иллюстрируется на следующем примере:
var set = [];
// Store a list of functions in an array
for (var i = 0; i<5; i++) {
set.push(function(){
console.log(i);
});
}
// Pull the functions back out and execute them
for (var x = 0; x<5; x++) {
set[x]();
}
Вывод этого:
5
5
5
5
5
Ожидается?Нет. Вы ожидаете 0, 1, 2, 3, 4
Это потому, что переменные, основанные на индексе для внешней области видимости (вне созданной вами функции), не копируются, их вычисляют, когдафункция выполняется (через некоторое время, после того, как цикл уже завершен).
Чтобы получить желаемый эффект, вы можете сделать любое из того, что я упомянул выше.Это (возможно, самое простое) - самоисполняющаяся анонимная функция :
var set = [];
// Store a list of functions in an array
for (var i = 0; i<5; i++) {
(function(i){
set.push(function(){
console.log(i);
});
})(i);
}
// Pull the functions back out and execute them
for (var x = 0; x<5; x++) {
set[x]();
}
Это дает вам желаемый результат 0, 1, 2, 3, 4, потому что мыустановил новую область видимости, создав новую функцию, передал интересующую нас переменную (i) и немедленно выполнил функцию с нужными параметрами.Он принимает базовую форму (function (a) {}) (a).
Не зная деталей вашего кода за пределами этого блока, вы можете сделать что-то вроде этого:
card.getcard(command, function(toproceed,resultscard) {
console.log('entry other cards api result'+sys.inspect(resultscard));
if (resultscard.length==0) {
return proceed(false,{errno:'011','queueno' : request.queueno, message:'there is no access card for particular gib'});
}
for (var i=0; i<resultscard.length;i++) {
(function(resultscard, i){
console.log('card owner'+resultscard[i].owner);
//checking that any users is in inside of gib
server.wrap(function(){
server.getchannel("channels."+request.gibid+'-I', function(err, channel) {
if (channel.users) {
var arr=channel.users.split(',');
if (functions.in_array(resultscard[i].owner, arr)) {
response.users.push(resultscard[i].owner);
}
}
});
if(i==resultscard.length-1) {
if (response.users.length<=0) {
//here need to send sorry event that no owner is online
request._command='sorry';
} else {
request._command='knock';
}
return proceed(true,response);
}
});
})(resultscard, i);
}
});