请解释闭包,或将循环计数器绑定到函数范围

发布于 2024-10-13 09:16:44 字数 284 浏览 4 评论 0原文

我见过程序员使用计数器在循环内分配事件侦听器。我相信这就是语法:

for(var i=0; i < someArray.length; i++){
   someArray[i].onclick = (function(i){/* Some code using i */})(i);
}

有人可以解释一下这背后的逻辑吗?这种奇怪的语法,我从未见过:

(function(i))(i);

非常感谢您的时间和耐心。

I've seen programmers assign events listeners inside loops, using the counter. I believe this is the syntax:

for(var i=0; i < someArray.length; i++){
   someArray[i].onclick = (function(i){/* Some code using i */})(i);
}

Could someone please explain the logic behind this, and this weird syntax, I've never seen this:

(function(i))(i);

Many thanks for your time and patience.

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

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

发布评论

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

评论(2

傾城如夢未必闌珊 2024-10-20 09:16:44

(function(i))(i) 语法创建一个匿名函数,然后立即执行它。

通常,您将在每次循环时创建一个新函数,该函数具有自己的变量副本,而不是每个事件处理程序共享相同的变量。

举个例子:

for(int i = 0; i < 10; i++)
    buttons[i].click = function() { doFoo(i); };

经常会让人出局,因为无论你点击哪个按钮,doFoo(10)都会被调用。

然而:

for(int i = 0; i < 10; i++)
    buttons[i].click = (function(i){ return function() { doFoo(i); };)(i);

为每次迭代创建内部函数的新实例(具有其自己的值i),并按预期工作。

The (function(i))(i) syntax creates an anonymous function and then immediately executes it.

Usually you'll do this to create a new function every time through the loop, that has its own copy of the variable instead of every event handler sharing the same variable.

So for example:

for(int i = 0; i < 10; i++)
    buttons[i].click = function() { doFoo(i); };

Often catches people out, because no matter what button you click on, doFoo(10) is called.

Whereas:

for(int i = 0; i < 10; i++)
    buttons[i].click = (function(i){ return function() { doFoo(i); };)(i);

Creates a new instance of the inner function (with its own value of i) for each iteration, and works as expected.

七七 2024-10-20 09:16:44

这样做是因为 JavaScript 只有函数作用域,而不是块作用域。因此,您在循环中声明的每个变量都在函数的范围内,并且您创建的每个闭包都可以访问相同的变量。

因此,创建新作用域的唯一方法是调用函数,这就是

(function(i){/* Some code using i */}(i))

正在做的事情。

请注意,您的示例遗漏了一个重要部分:立即函数必须返回另一个函数,该函数将成为 click 处理程序:

someArray[i].onclick = (function(i){
    return function() {
       /* Some code using i */
    }
}(i));

立即函数没有什么特别的。它以某种方式内联函数定义和函数调用。您可以将其替换为普通函数调用:

function getClickHandler(i) {
    return function() {
         /* Some code using i */
    }
}

for(var i=0; i < someArray.length; i++){
   someArray[i].onclick = getClickHandler(i);
}

This is done because JavaScript only has function scope, not block scope. Hence, every variable you declare in a loop is in the function's scope and every closure you create has access to the very same variable.

So the only way to create a new scope is to call a function and that is what

(function(i){/* Some code using i */}(i))

is doing.

Note that your example misses an important part: The immediate function has to return another function which will be the click handler:

someArray[i].onclick = (function(i){
    return function() {
       /* Some code using i */
    }
}(i));

The immediate function is nothing special. It is somehow inlining function definition and function call. You can replace it by a normal function call:

function getClickHandler(i) {
    return function() {
         /* Some code using i */
    }
}

for(var i=0; i < someArray.length; i++){
   someArray[i].onclick = getClickHandler(i);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文