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