Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
188 views
in Technique[技术] by (71.8m points)

javascript - JavaScript臭名昭著的循环问题? [重复](Javascript infamous Loop issue? [duplicate])

This question already has an answer here:

(这个问题已经在这里有了答案:)

I've got the following code snippet.

(我有以下代码片段。)

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

The above code is for generating 5 links and bind each link with an alert event to show the current link id.

(上面的代码用于生成5个链接,并将每个链接与警报事件绑定以显示当前链接ID。)

But It doesn't work.

(但这行不通。)

When you click the generated links they all say "link 5".

(当您单击生成的链接时,它们都说“链接5”。)

But the following codes 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);
    }
}

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?

(谁能提供有关魔术的详细解释?)

thanks.

(谢谢。)

  ask by Zhu Tao translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Quoting myself for an explanation of the first example:

(引用我自己来解释第一个示例:)

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.

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

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

(循环终止后,函数级变量i的值为5,这就是内部函数所看到的。)

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 .

(在第二个示例中,对于每个迭代步骤,外部函数文字将评估为具有自己的作用域和局部变量num的新函数对象,其值设置为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.

(由于num从未修改,因此它将在闭包的整个生命周期内保持不变:由于函数对象是独立的,因此下一个迭代步骤不会覆盖旧值。)

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:

(这是不必要的,因为如果您使用DOM节点进行信息存储,则可以轻松共享它们:)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...