匿名函数中的JavaScript上下文

时间:2011-02-04 15:59:00

标签: javascript scope anonymous-function

我想将一个函数设置为数组中每个元素的属性,但是使用不同的参数调用它。我以为我会用匿名函数来解决它:

for ( var i = 0; i < object_count; i++ ) {
    objects[i].callback = function(e,x,y){ cb(e,x,y,i) };
}

但是,使用i当时具有的值调用该函数。我如何保留上下文?

2 个答案:

答案 0 :(得分:10)

您可以将作业至少包含在一个函数或右侧:

    objects[i].callback = (function(i) { return function(e, x, y) {
      cb(e, x, y, i);
    })(i);

立即调用“外部”匿名函数,将循环变量“i”复制到一个参数中(我也称之为“i”;有些人认为这样做会让人感到困惑,而其他人则认为它令人困惑不是< / em>这样做,所以你可以决定:-)然后由返回的“内部”匿名函数使用。

解决此问题的另一种方法是使用实​​用程序函数来代替简单的内联匿名函数。在这种情况下,它有点棘手,因为你希望“i”成为实际回调函数的 last 参数。 Functional JavaScript库有一个很酷的实用程序,它允许您使用固定值“预填充”函数的选定参数,为您提供一个函数,允许您将参数传递给非固定的参数;它看起来像这样:

  objects[i].callback = (function(e, x, y, i) { return cb(e, x, y, i); }).partial(_, _, _, i);

无论是好还是坏都是风格和观点的问题。

编辑只是喝了一点咖啡 - 我觉得我有点傻了,以至于我不得不在上面使用“partial()”。内部(“真实”函数)在参数列表的末尾想要“i”的事实与需要设置事物的方式无关。以上示例也可以这样做:

   objects[i].callback = (function(i, e, x, y) { return cb(e, x, y, i); }).curry(i);

这不那么奇怪。 (要么会工作。至少,我认为他们会。: - )

答案 1 :(得分:3)

写作时

for (var i = something; ...) {
  a[i] = function() { x(i); }
}

函数中的i对于所有函数都是相同的(它是您在for循环范围内定义的相同变量。

您要做的是拥有一个特定于每个函数上下文的变量。你可以做这样的事情

for (var i = something; ...) {
  (function () {        // using an anonymous function, we create a private context
     var new_i = i;     // new_i has the value of 'i' but exists solely in this
                        // private context
     a[i] = function() { x(new_i); }
                        // the assigned function now refers a variable of the private
                        // context, which will be different on the following loop
                        // iterations
  })();
}

通过搜索JavaScript中闭包和范围的工作方式,您可以获得有关此主题的更多信息。