3
for(var i=1; i<496; i++) {
    (function(num) {
        myApp.getTerm(num, function (term, def){
            myApp.quizlet[0].terms[num] = { term: term, definition: def};
        });         
    })(i);
};

我在 for 循环中调用带有回调的函数。回调函数需要访问当前循环的迭代i 。我想出了上面的解决方案。

有没有其他方法可以做这样的事情?

4

5 回答 5

2

您正在做的事情并非不合理,应该可以正常工作。纯粹在可读性层面上,我可能会选择

for(var i=1; i<496; i++) {
    function get_callback(n) {
        return function(term, def) {
            myApp.quizlet[0].terms[n] = { term: term, definition: def};
         };
    }
    myApp.getTerm(i, get_callback(i));         
};

如果您习惯使用 Function.bind:

function callback (n, term, def) {
    myApp.quizlet[0].terms[n] = { term: term, definition: def};
}
for(var i=1; i<496; i++) {
    myApp.getTerm(i, callback.bind(this,i));
}

我们将第一个参数绑定到,从而产生一个采用and参数i的“咖喱”函数。termdef

然后当然有这个可怕的黑客,不要在家里尝试这个。

for(var i=1; i<496; i++) {
    try { throw i; }
    catch (i) {
        myApp.getTerm(i, function (term,def) {
             myApp.quizlet[0].terms[i] = { term: term, definition: def};
        });
    }
}
于 2012-06-23T01:08:11.937 回答
2

定义要调用的命名函数更具可读性:

myApp.getTermForQuizzlet = function(num){
    myApp.getTerm(num, function (term, def){
        myApp.quizlet[0].terms[num] = { term: term, definition: def };
    });         
};

for(var i=1; i<496; i++) {
    myApp.getTermForQuizzlet(i);
};

除此之外,我不知道你还能做什么。

于 2012-06-23T01:00:17.263 回答
1

循环内部的结构称为立即调用函数表达式(IIFE)。

例如,当您在循环中创建事件处理程序并希望为每个事件处理程序锁定循环变量的当前值以供以后使用时,IIFE 可能很有用。这种“锁定”称为(词法或函数)闭包:外部函数(在您的情况下为 IIFE)的词法范围,包括任何常量、局部变量和参数值(在您的情况下num为 IIFE 的参数,其中是循环变量的实际值),成为每个内部函数对象(在您的情况下,传递给的回调函数myApp.getTerm)的内部状态的一部分,即使在外部函数(IIFE)执行结束之后也是如此。

所以我认为你这样做是对的,在你的情况下使用 IIFE 是一个完全有效的解决方案。

这种模式的一个有趣的例子(闭包的 IIFE)可以在John Resig 的继承实现中找到:

// ...
(function(name, fn){
  return function() {
    // use name and fn here
  };
})(name, prop[name])
// ...
于 2012-06-23T01:01:40.800 回答
1

大多数时候,我使用迭代函数而不是 bulidtin 循环。它们在较新的浏览器和大多数 JS 库中可用:

array.forEach(function(item, i){
    //We can freely use "item" and "i" in callbacks without worrying
    setTimeout( function(){ console.log(item, i) }, 1000 );
});

这通常比 for-loop 版本更短(如果您至少在数组上迭代)并且它避免了“免费”的闭包循环错误,而无需添加额外的立即调用函数或类似的东西那。

此方法的主要缺点是它不支持使用“this”和使用 break、continue 和 return 语句以及内置循环,并且大多数库仅提供用于数组或字典迭代的函数,不支持更多一般循环样式。虽然我很少最终需要这种高级功能,但当它出现时,我通常只使用额外的闭包(就像你所做的那样),或者,如果它是一种常见的模式,则编写我自己的迭代器函数。

var forLoop = function(i0, n, f){
    for(var i=i0; i<n; i++){
        f(i);
    }
};

forLoop(1, 496, function(i){
    myApp.getTerm(i, function(term, def){
        myApp.quizlet[0].terms[i] = { ... }
    });
});
于 2012-06-23T01:02:02.223 回答
1

似乎您基本上希望

  1. 创建应用程序,myApp;
  2. 将属性 .quiz 添加到 myApp;
  3. 将属性 .terms 添加到 .quiz;
  4. 对于测验中的每个术语,形成一个对象以将每个术语与其定义相关联。

要设置您需要的属性,您可以执行以下操作..

var terms = ['js', 'php', 'css', 'html', 'as3'];
var defin = ['about js', 'about php', 'about css', 'about html', 'about as3'];
var myApp = {};
myApp.quiz = new Array;
myApp.quiz[0] = [];
myApp.quiz[0].terms = new Array;

terms.forEach(function(ele, idx){
    myApp.quiz[0].terms[idx] = {term: terms[idx], def: defin[idx]};
})

现在,您需要一种方法来访问任何测验中的任何术语。所以你可以用一个函数来做到这一点,比如 ..

function getTerm(qn, tn){
  return myApp.quiz[qn].terms[tn];
}
var q0t2 = getTerm(0, 2);
console.log(q0t2); // def: "about css", term: "css"

我不太确定您的需求是什么,但这是我最好的猜测。如果您的情况不适合我在这里使用的那种方法,请详细说明。:)

于 2012-06-23T02:50:59.390 回答