JavaScript closures and variable scope
我在JS闭包时遇到问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // arg: an array of strings. each string is a mentioned user. // fills in the list of mentioned users. Click on a mentioned user's name causes the page to load that user's info. function fillInMentioned(mentions) { var mentionList = document.getElementById("mention-list"); mentionList.innerHTML =""; for (var i = 0; i < mentions.length; i++) { var newAnchor = document.createElement("a"); // cause the page to load info for this screen name newAnchor.onclick = function () { loadUsernameInfo(mentions[i]) }; // give this anchor the necessary content newAnchor.innerHTML = mentions[i]; var newListItem = document.createElement("li"); newListItem.appendChild(newAnchor); mentionList.appendChild(newListItem); } document.getElementById("mentions").setAttribute("class",""); // unhide. hacky hack hack. } |
不幸的是,单击其中一个锚标签会导致这样的调用:
1 | loadUserNameInfo(undefined); |
为什么是这样? 我的目标是像这样的锚:
1 | someguy |
我该如何制作?
更新此作品:
1 2 | newAnchor.onclick = function () { loadUsernameInfo(this.innerHTML) }; newAnchor.innerHTML = mentions[i]; |
闭包内的onclick处理程序的"i"引用正在捕获"i"的实时引用。 它会针对每个循环进行更新,这会影响到目前为止创建的所有闭包。 当你的while循环结束时,"i"刚好超过了mentions数组的结尾,所以提到[i] == undefined为所有这些。
做这个:
1 2 3 | newAnchor.onclick = (function(idx) { return function () { loadUsernameInfo(mentions[idx]) }; })(i); |
强制"i"锁定闭包内的值idx。
您的迭代器
试试这个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | function fillInMentioned(mentions) { var mentionList = document.getElementById("mention-list"); mentionList.innerHTML =""; for (var i = 0; i < mentions.length; i++) { var newAnchor = document.createElement("a"); // Set the index as a property of the object newAnchor.idx = i; newAnchor.onclick = function () { // Now use the property of the current object loadUsernameInfo(mentions[this.idx]) }; // give this anchor the necessary content newAnchor.innerHTML = mentions[i]; var newListItem = document.createElement("li"); newListItem.appendChild(newAnchor); mentionList.appendChild(newListItem); } document.getElementById("mentions").setAttribute("class",""); } |