将onchange函数事件附加到变量

时间:2011-04-21 13:21:39

标签: javascript closures onchange

我最近进入了闭包和匿名函数,我想知道我的代码是否是正确的方法(它有效!):

newInput.onchange = function(x){
     return function(){
          PassFileName(x);  
     }
}(counter);

所以这是一个“保存”当前“计数器”值(1,2,3 ...)的循环。如果我没有返回函数,那么'counter'将始终是'counter'的最后一个值。

我是否正确使用该代码?或者是否有更好的方法来“捕获”当前计数器并将其附加到onchange事件?

谢谢你!

2 个答案:

答案 0 :(得分:5)

是的,您正确地接近它,但为了最大程度地兼容实现,您需要在函数周围添加括号:

    newInput.onchange = (function(x){
//                      ^--- here
         return function(){
              PassFileName(x);  
         }
    })(counter);
//   ^--- and here

每当你做一个函数表达式并立即调用它时,你需要那些parens,因为否则会有解析歧义。


<强>更新

虽然你的方法很好,但值得指出的是它有点挥霍。 ;-)它在循环的每次迭代中创建两个函数,外部匿名函数和内部匿名函数。这两个功能都存在(除非实现优化,你知道一些引擎不会有)。相反,你可以只有一个循环加上一个工厂函数:

// In the loop
newInput.onchange = makeHandler(x);

// Outside the loop
function makeHandler(x){
     return function(){
          PassFileName(x);  
     };
}

有些人可能会认为它更容易阅读(我当然这样做),前提是makeHandler仍然足够接近您不会失去跟踪的循环。

使用工厂功能还为您提供了不关闭范围内任何 else 的机会,尽管您必须将工厂功能放得更远(例如,在一个包含良好的范围内)。

您可能还会考虑通用curry功能,例如the one provided by Prototype传递调用时参数的通用curry如下所示:

function curry(f) {
    var args = arguments;
    return function() {
        f.apply(undefined, args);
    };
}

但是,让 传递一个运行时参数的通常更有帮助(但更昂贵)。这是一个廉价和肮脏(未优化;优化调用时间开销可以显着减少):

function curry(f) {
    var args = Array.prototype.slice.call(arguments, 1);
    return function() {
        f.apply(undefined,
                args.concat(Array.prototype.slice.call(arguments)));
    };
}

两种情况下的优势在于,您不会关闭任何可以避免的新内容。


偏离主题:另外,技术上,你依赖于分号插入的恐怖(你{{1}末尾应该有一个分号声明),我一直主张不依赖。但是,在这个例子中,相当安全。 ; - )

答案 1 :(得分:3)

你所做的是相当标准的,并没有任何问题。但是,我更喜欢类似的方法:

(function (x) {
    newInput.onchange = function () {
        PassFileName(x);
    };
})(counter);

对我而言,通过包装整个块(以及缩进)更清楚我正在考虑创建一个新的范围以捕获变量的值。