Skip to content

Instantly share code, notes, and snippets.

@toctan
Last active May 11, 2016 09:18
Show Gist options
  • Save toctan/6222729 to your computer and use it in GitHub Desktop.
Save toctan/6222729 to your computer and use it in GitHub Desktop.
var list = document.getElementById("list");
for (var i = 1; i <= 5; i++) {
var item = document.createElement("LI");
item.appendChild(document.createTextNode("Item " + i));
item.onclick = function (ev) {
alert("Item " + i + " is clicked.");
};
list.appendChild(item);
}
// 上面的代码不能够正常运行,无论点击哪一个 item, alert 的都是 ”Item 5 is clicked."
// item.onclick 事件注册的五个函数全是 closures, 包含函数定义以及当前域的 environment,
// 这五个 closures 享有同一个 environment,当函数被调用的时候,该 environment 内的 i 已经是 5了
// 正确的做法如下,使用一个 function factory: makeCallback 返回 callback 函数
function makeCallback(i) {
return function() {
alert("Item " + i + " is clicked.");
};
}
var list = document.getElementById("list");
for (var i = 1; i <= 5; i++) {
var item = document.createElement("LI");
item.appendChild(document.createTextNode("Item " + i));
item.onclick = makeCallback(i);
list.appendChild(item);
}
// 使用 JavaSctipt 1.7 中的 let 也能解决这问题,但是支持 1.7 的只有 Mozilla 的浏览器
var list = document.getElementById("list");
for (var i = 1; i <= 5; i++) {
var item = document.createElement("LI");
item.appendChild(document.createTextNode("Item " + i));
let j = i;
item.onclick = function (ev) {
alert("Item " + j + " is clicked.");
};
list.appendChild(item);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment