Fermetures de JavaScript et portée variable

J'ai des problèmes avec les fermetures de JS:

// 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. } 

Malheureusement, en cliquant sur l'une de ces marques d'ancrage, vous obtenez un appel comme celui-ci:

 loadUserNameInfo(undefined); 

Pourquoi est-ce? Mon objectif est une ancre comme ceci:

 <a onclick="loadUserNameInfo(someguy)">someguy</a> 

Comment puis-je produire cela?

Mise à jour Ceci fonctionne:

 newAnchor.onclick = function () { loadUsernameInfo(this.innerHTML) }; newAnchor.innerHTML = mentions[i]; 

La référence "i" à l'intérieur de la fermeture pour les gestionnaires onclick trappe une référence en direct sur "i". Il est mis à jour pour chaque boucle, ce qui affecte toutes les fermetures créées jusqu'à présent. Lorsque votre boucle while se termine, "i" est juste après la fin du tableau mentions, alors mentionne [i] == indéfini pour tous.

Faire cela:

 newAnchor.onclick = (function(idx) { return function () { loadUsernameInfo(mentions[idx]) }; })(i); 

Pour forcer le "i" à verrouiller dans une valeur idx à l'intérieur de la fermeture.

Votre itérateur i est stocké en tant que référence, non comme valeur et donc, lorsqu'il est modifié en dehors de la fermeture, toutes les références sont en train de changer.

essaye ça

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