Yaz*_*Yaz 5 javascript closures event-handling
我试图在onclick事件处理函数中获取一个对象.
但它并没有像我期望的那样发挥作用.
例如,如果我运行此代码:
var entries = [{id: 1},{id: 2},{id: 3}];
for (var i = 0; i < entries.length; i++) {
var entry = entries[i];
document.getElementById(entry.id).onclick = function () {
console.log("this.id: " + this.id);
console.log("entry.id: " + entry.id);
};
}
Run Code Online (Sandbox Code Playgroud)
我的期望是:
this.id: 1
entry.id: 1
this.id: 2
entry.id: 2
this.id: 3
entry.id: 3
Run Code Online (Sandbox Code Playgroud)
但我得到的是:
this.id: 1
entry.id: 3
this.id: 2
entry.id: 3
this.id: 3
entry.id: 3
Run Code Online (Sandbox Code Playgroud)
为什么条目对象始终是id为3的条目?
如何在click事件处理程序中获取正确的条目对象?
解决此问题的一种方法是:
var entries = [{id: 1},{id: 2},{id: 3}];
for (var i = 0; i < entries.length; i++) {
var entry = entries[i];
document.getElementById(entry.id).onclick = (function (id) {
return function () {
console.log("this.id: " + this.id);
console.log("entry.id: " + id);
};
})(entry.id);
}
Run Code Online (Sandbox Code Playgroud)
您可以使用自执行函数(其目的是提供entry.id将绑定的闭包)来返回绑定到特定id的新onclick处理程序.
如果不这样做,所有onclick处理程序都绑定到相同的条目变量,并以for循环期间收到的最后一个值结束.
这是因为 JavaScript 中闭包的工作方式。所有 3 个元素上的 onclick 引用存储相同的函数,该函数在循环之后具有指向最后一个条目的条目。于是就有了这样的结果。您可以通过将其包装在具有所需条目的另一个函数中来获得结果。以下是一种方法:
var entries = [{id: 1},{id: 2},{id: 3}];
for (var i = 0; i < entries.length; i++) {
var entry = entries[i];
function setOnClickHandler(entry) {
document.getElementById(entry.id).onclick = function () {
console.log("this.id: " + this.id);
console.log("entry.id: " + entry.id);
};
}
setOnClickHandler(entry);
}
Run Code Online (Sandbox Code Playgroud)
我已经就此写了一篇小文章。