3

长话短说:

var o="before";
x = function() //this needs to be an anonymous function
{
  alert(o); //the variable "o" is from the parent scope
};
o="after"; //this chages "o" in the anonymous function

x();
//this results in in alert("after");
//which is not the way i want/need it

实际上,我的代码要复杂一些。

我的脚本遍历许多 html 对象并为每个元素添加一个事件侦听器。

我通过为每个元素声明一个匿名函数并使用 ID 作为参数调用另一个函数来做到这一点。在本例中,该 ID 由“o”变量表示。

经过一番思考,我明白了为什么会这样,但是有没有办法让 js 在我声明匿名函数时评估 o 而无需处理 id 属性并从那里获取我的 ID?

我的完整源代码在这里: http: //pastebin.com/GMieerdw

匿名函数在第 303 行。

4

3 回答 3

8

您需要为您的变量创建一个闭包o。您可以通过分配一个接受值的函数返回一个使用该值的函数来做到这一点。您可以像这样修改您的示例以获得所需的效果:

var o="before";
x = function(inner) {
    return function()
    {
      alert(inner);
    }
} (o); //here, the anonymous function is called, which will return another function which uses o
o="after";

x();//prints "before"

有关更详细的描述,请参阅MDC 文章,其中有一节关于使用带有循环的闭包。

可以在您的循环中应用相同的技术。像这样的事情是你想要做的:

var fn = function(x, y) {
    return function() {
        rr_download_start(x, y);
    }
} (i, this);
link.addEventListener('click', fn ,false);
于 2010-05-10T21:56:50.827 回答
6

您可以尝试使用这样的自调用函数:

var o = 0;
for(var i=0;i<elements.length;i++){
    (function(obj,variable){
        obj.onclick = function(){
            alert(variable);
        }
    })(elements[i],o);
    o++;
}

这应该在循环期间以任何值提醒“o”,而不是提醒“o”的最终值。

我希望这在某种程度上有所帮助。

于 2010-05-10T21:48:52.857 回答
0

一种方法是创建一个柯里化函数:

function curry(fun, arg) {
  return function() {
    return fun(arg);
  };
};

// start loop 
var o="before";
x = curry(function(o) {
  alert(o);
}, o);
o="after";

x(); // "before"

另一种方法是使用外部数据源 - 因为this将取决于调用函数的位置,您可以将值存储在绑定处理程序的 DOM 节点中。这样您就可以使用单个函数而不是许多匿名函数。这种技术有一些注意事项(循环引用会导致 IE6 中的内存泄漏),但框架可以有一个很好的干净包装器。例如。在 jQuery 中你可以写:

function doStuff() {
  alert($(this).data('o'));
}

// start loop
var o="before";
someDomElement.data('o', 'before');
someDomElement.bind('someEvent', doStuff);
o="after";

someDomElement.trigger('someEvent'); // "before"
于 2010-05-10T22:21:41.093 回答