Javascript 将onchange函数事件附加到变量

Javascript 将onchange函数事件附加到变量,javascript,closures,onchange,Javascript,Closures,Onchange,我最近接触了闭包和匿名函数,我想知道我的代码是否是正确的方法(它可以工作!): 这是一个“保存”当前“计数器”值(1,2,3…)的循环。如果我没有返回函数,那么“counter”将始终是“counter”的最后一个值 我用那个代码处理这个问题正确吗?还是有更好的方法“捕获”当前计数器并将其附加到onchange事件 谢谢大家! 你所做的是相当标准的,没有任何问题。但是,我更喜欢一种类似的方法: (function (x) { newInput.onchange = function ()

我最近接触了闭包和匿名函数,我想知道我的代码是否是正确的方法(它可以工作!):

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

我用那个代码处理这个问题正确吗?还是有更好的方法“捕获”当前计数器并将其附加到onchange事件


谢谢大家!

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

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

对我来说,通过包装整个块(以及缩进),我正在考虑创建一个新的作用域,以捕获变量的值,这一点更加清楚。

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

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

// Outside the loop
function makeHandler(x){
     return function(){
          PassFileName(x);  
     };
}
每当你在做一个函数表达式并立即调用它时,你都需要这些参数,因为在其他情况下,解析是不明确的


更新

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

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

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

有些人可能认为读起来更容易(当然我会这样做),只要<代码> Mauffer-Huffer-仍然足够接近你不会丢失的循环。

使用工厂函数还可以让您不关闭范围内的任何其他功能,尽管这样您必须将工厂函数放在更远的地方(例如,在一个包含良好的范围内)

你也可以考虑一个泛型函数。不传递调用时参数的通用

curry
如下所示:

function curry(f) {
    var args = arguments;
    return function() {
        f.apply(undefined, args);
    };
}
但是,如果有一个能够传递运行时参数的函数,通常会更有帮助(但成本更高)。这是一个便宜且肮脏的方法(未经优化;通过优化,通话时间开销可以显著减少):

在这两种情况下的优点是,你不会关闭任何新的,你可以避免



离题:另外,从技术上讲,您依赖的是分号插入(您的
return
语句末尾应该有一个分号),我一直主张不要依赖这个分号。但在这个例子中非常安全。;-)

这种方法需要注意的一点是,只要函数仍然是侦听器,就会创建并保持无用的闭包。确保外部函数不会不必要地挂起对大型对象或变量的引用。当外部范围中没有引用时,实现可能(有些确实)优化它们,但这曾经是在IE中创建内存泄漏的一个很好的方法。同意这一点。不过,请参见上文@RobG的观点。这样做意味着一个实现几乎肯定不能优化掉外部函数,因为它(现在)在其变量对象上有内部函数需要的东西(
x
参数)@wata的方法至少为引擎提供了优化冗余工厂函数的机会…@T.J.我同意正在创建的多余函数,如果您的需求超出了一些快速和肮脏的代码,那么您的
makeHandler
更新肯定是一个更好的选择(+1!)。我不明白我的例子和@wata的例子之间的自动优化有什么不同?@Box9:是的,这很棘手。:-)调用函数时,将创建一个执行上下文。执行上下文有一个关联的变量对象,该对象具有每个参数、每个
var
和函数声明的每个结果(不是函数表达式)的属性。该变量对象放在作用域链的顶部,用于解析非限定引用(如
x
)。闭包就是这样工作的,函数保持对变量对象的引用(变量对象反过来引用链中的下一个对象,等等)。(续)@Box9:(继续)在@wata的版本中,外部函数调用的变量对象将为空,但在您的版本中,外部函数的
x
参数将具有
x
属性。与变量对象上有内容相比,优化器更有可能发现它可以丢弃带有空变量对象(以及变量对象和执行上下文)的函数。当我说“blank”时,变量对象从来都不是真正的空白(它至少有一个名为
arguments
的属性),但比方说,除了它总是有的东西之外,它是空白的。:-)@谢谢你的解释。我理解你对变量对象的看法,但是在@wata的版本中,外部函数也有一个参数
x
。那么为什么在这种情况下变量对象是“空白”的呢?