- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我有以下代码片段。
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 个链接并将每个链接与警报事件绑定(bind)以显示当前链接 ID。但它不起作用。当您单击生成的链接时,它们都会显示“链接 5”。
但下面的代码片段符合我们的预期。
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);
}
}
以上两段摘自here .正如作者的解释,似乎 闭包 具有魔力。
但它是如何工作的,以及 closure 如何使它工作,这一切都超出了我的理解。为什么第一个不起作用,而第二个起作用?谁能详细解释一下魔法?
最佳答案
Quoting myself关于第一个例子的解释:
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.
After the loop terminates, the function-level variable i has the value 5, and that's what the inner function 'sees'.
在第二个示例中,对于每个迭代步骤,外部函数字面量将评估为具有自己的范围和局部变量 num
的新函数对象。 ,其值设置为 i
的当前值.如num
永远不会被修改,它将在闭包的生命周期内保持不变:下一个迭代步骤不会覆盖旧值,因为函数对象是独立的。
请记住,这种方法效率很低,因为必须为每个链接创建两个新的函数对象。这是不必要的,因为如果您使用 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);
}
}
关于Javascript臭名昭著的循环问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1451009/
我是一名优秀的程序员,十分优秀!