JS:匿名函数中的变量继承 - 范围

时间:2010-05-10 21:44:12

标签: javascript scope anonymous-function

嘿伙计们,来自doctype的人把我送到了这里 长话短说:

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行

3 个答案:

答案 0 :(得分: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"

有关更详细的说明,请参阅the MDC article,其中有一节介绍如何使用带循环的闭包。

这种技术可以在你的循环中应用。这样的事情就是你想做的事情:

var fn = function(x, y) {
    return function() {
        rr_download_start(x, y);
    }
} (i, this);
link.addEventListener('click', fn ,false);

答案 1 :(得分: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”的最终值。

我希望这会有所帮助。

答案 2 :(得分:0)

一种方法是创建currying函数:

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中的内存泄漏),但框架可以有一个很好的干净包装。 E. g。在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"