将onchange函数事件附加到变量

wat*_*ata 6 javascript closures onchange

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

newInput.onchange = function(x){
     return function(){
          PassFileName(x);  
     }
}(counter);
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢!

T.J*_*der 5

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

    newInput.onchange = (function(x){
//                      ^--- here
         return function(){
              PassFileName(x);  
         }
    })(counter);
//   ^--- and here
Run Code Online (Sandbox Code Playgroud)

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


更新:

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

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

// Outside the loop
function makeHandler(x){
     return function(){
          PassFileName(x);  
     };
}
Run Code Online (Sandbox Code Playgroud)

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

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

您可能还会考虑一般的咖喱功能,例如Prototype提供的功能.一个通用curry的是上呼叫时间传递参数如下:

function curry(f) {
    var args = arguments;
    return function() {
        f.apply(undefined, args);
    };
}
Run Code Online (Sandbox Code Playgroud)

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

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

两种情况下的优势在于,您不会关闭任何可以避免的新事物.


偏离主题:另外,从技术上讲,你依赖于分号插入的恐怖(在你的return陈述结尾应该有一个分号),我一直主张不依赖分号.但是,在这个例子中,相当安全.;-)