Javascript 臭名昭著的循环问题? [英] Javascript infamous Loop issue?

查看:33
本文介绍了Javascript 臭名昭著的循环问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码片段.

function addLinks () {
    for (var i=0, link; i<5; i++) {
        link = document.createElement("a");
        link.innerHTML = "Link " + i;
        link.onclick = function () {
            alert(i);
        };
        document.body.appendChild(link);
    }
}

以上代码用于生成 5 个链接,并将每个链接与警报事件绑定以显示当前链接 id.但它不起作用.当您点击生成的链接时,它们都会显示链接 5".

The above code is for generating 5 links and binding each link with an alert event to show the current link id. But It doesn't work. When you click the generated links they all say "link 5".

但以下代码片段符合我们的预期.

But the following code snippet works as our expectation.

function addLinks () {
    for (var i=0, link; i<5; i++) {
        link = document.createElement("a");
        link.innerHTML = "Link " + i;
        link.onclick = function (num) {
            return function () {
                alert(num);
            };
        }(i);
        document.body.appendChild(link);
    }
}

以上 2 个片段引用自 这里.正如作者的解释似乎闭包创造了魔力.

The above 2 snippets are quoted from here. As the author's explanation seems the closure makes the magic.

但是它是如何工作的以及如何闭包使它工作都超出了我的理解.为什么第一个不起作用而第二个起作用?谁能详细解释一下这个魔法?

But how it works and How closure makes it work are all beyond my understanding. Why the first one doesn't work while the second one works? Can anyone give a detailed explanation about the magic?

推荐答案

引述我自己来解释第一个例子:

JavaScript 的作用域是函数级的,而不是块级的,创建闭包只是意味着将封闭作用域添加到封闭函数的词法环境中.

JavaScript's scopes are function-level, not block-level, and creating a closure just means that the enclosing scope gets added to the lexical environment of the enclosed function.

循环终止后,函数级变量 i 的值为 5,这就是内部函数看到"的.

After the loop terminates, the function-level variable i has the value 5, and that's what the inner function 'sees'.

在第二个示例中,对于每个迭代步骤,外部函数文字将评估为具有自己的作用域和局部变量 num 的新函数对象,其值设置为 i.由于 num 永远不会被修改,它将在闭包的整个生命周期中保持不变:由于函数对象是独立的,因此下一个迭代步骤不会覆盖旧值.

In the second example, for each iteration step the outer function literal will evaluate to a new function object with its own scope and local variable num, whose value is set to the current value of i. As num is never modified, it will stay constant over the lifetime of the closure: The next iteration step doesn't overwrite the old value as the function objects are independant.

请记住,这种方法效率很低,因为必须为每个链接创建两个新的函数对象.这是不必要的,因为如果您使用 DOM 节点进行信息存储,它们可以很容易地共享:

Keep in mind that this approach is rather inefficient as two new function objects have to be created for each link. This is unnecessary, as they can easily be shared if you use the DOM node for information storage:

function linkListener() {
    alert(this.i);
}

function addLinks () {
    for(var i = 0; i < 5; ++i) {
        var link = document.createElement('a');
        link.appendChild(document.createTextNode('Link ' + i));
        link.i = i;
        link.onclick = linkListener;
        document.body.appendChild(link);
    }
}

这篇关于Javascript 臭名昭著的循环问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆