将 onchange 函数事件附加到变量

发布于 2024-11-02 20:28:08 字数 337 浏览 1 评论 0原文

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

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

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

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

谢谢你!

I recently got into closures and anonymous functions, and I'm wondering if my code is the right way to do it (it works!):

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

so this is in a loop that "saves" the current 'counter' value (1,2,3...). If I didn't have the return function, then 'counter' will always be the last value of 'counter'.

Am I approaching this correctly with that code? or is there a better way to "capture" the current counter and attach it to an onchange event?

thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

强者自强 2024-11-09 20:28:08

是的,您正在正确地处理它,但是为了与实现实现最大程度的兼容性,您需要在函数周围放置括号:

    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);  
     };
}

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

使用工厂函数还为您提供了不关闭范围内任何其他内容的机会,尽管您必须将工厂函数放在更远的地方(例如,在一个包含良好的范围中)。

您还可以考虑使用通用的 curry 函数,例如 Prototype 提供的。一种不会传递调用时参数的通用curry看起来像这样:

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

但是拥有一个会<的通常会更有帮助(但更昂贵) /em> 也传递运行时参数。这是一种廉价而肮脏的方法(未优化;通过优化,可以显着减少调用时间开销):

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

这两种情况的优点是您不会关闭任何可以避免的新内容。


离题:此外,技术上,您依赖的是分号插入的恐怖(您的返回符末尾应该有一个分号 声明),我一直主张不要依赖它。不过,在这个例子中非常安全。 ;-)

Yes, you're approaching it correctly, but for maximum compatibility with implementations, you need to put parentheses around the function:

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

Whenever you're doing a function expression and calling it immediately, you need those parens because there's a parsing ambiguity otherwise.


Update:

While your approach is fine, it's worth pointing out that it's a bit profligate. ;-) It creates two functions on every iteration of your loop, the outer anonymous one, and the inner anonymous one. Both of those functions stick around (barring implementation optimisations, which you know Some Engines won't have). Instead, you could have just one per loop plus one factory function:

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

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

Some may consider it easier to read (I certainly do), provided the makeHandler is still close enough to the loop that you don't lose track.

Using a factory function also offers you the opportunity of not closing over anything else in scope, although then you have to put the factory function further away (e.g., in a well-contained scope).

You might also consider a generic curry function, like the one provided by Prototype. A generic curry that doesn't pass on call-time arguments looks like this:

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

But it's usually more helpful (but more expensive) to have one that does pass on the runtime arguments as well. Here's a cheap-and-dirty (not optimised; with optimisation call-time overhead can be markedly reduced):

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

The advantage in both cases is that you're not closing over anything new that you can avoid.


Off-topic: Also, technically, you're relying on the horror that is semicolon insertion (there should be a semicolon at the end of your return statement), which I always advocate not relying on. Pretty darned safe in this example, though. ;-)

阪姬 2024-11-09 20:28:08

你所做的事情是相当标准的,没有什么问题。然而,我更喜欢一种类似的方法:

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

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

What you're doing is fairly standard, and there's nothing wrong with it. However, there's a similar method which I prefer:

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

To me, it is clearer by wrapping the whole block (and with the indentation) that I'm deliberating creating a new scope in order to capture the value of a variable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文