2010-02-22 3 views
3

Je ne parviens pas à des fermetures de JS:fermetures de JavaScript et la portée des variables

// 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'un de ces balises d'ancrage des résultats dans un appel comme celui-ci:

loadUserNameInfo(undefined); 

Pourquoi est-ce? Mon objectif est une ancre comme celle-ci:

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

Comment puis-je produire ceci?

Mise à jour Cela fonctionne:

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

Ceci est l'une des questions les plus courantes et répétitives ici concernant les fermetures, duplicates possible: http://stackoverflow.com/questions/1734749/ http://stackoverflow.com/questions/643542/ http : //stackoverflow.com/questions/1582634/ http://stackoverflow.com/questions/1331769/ http://stackoverflow.com/questions/1552941/ http://stackoverflow.com/questions/750486/ http://stackoverflow.com/questions/933343/ http: //stackoverflow.c om/questions/1579978/ http://stackoverflow.com/questions/1413916/ – CMS

Répondre

7

Le « i » référence à l'intérieur de la fermeture pour les gestionnaires onclick est le piégeage référence direct « 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, donc mentionne [i] == indéfini pour chacun d'eux.

Faites ceci:

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

pour forcer le "i" pour verrouiller en une valeur IDX à l'intérieur de la fermeture.

+0

qui ne fonctionne pas. Les mentions ne sont pas une variable globale, elles ne seraient donc pas accessibles depuis une fonction 'onclick', n'est-ce pas? –

+0

Comme Ben l'a souligné, ma réponse était erronée. J'allais le reformuler exactement comme ça. +1 et désolé si j'ai confondu quelqu'un –

+1

@Rosarch toutes les variables/fonctions d'une portée 'supérieure' peuvent être vues dans une portée 'inférieure'. –

2

Votre iterator i est stocké comme référence, et non comme une valeur et ainsi, comme il est changé en dehors de la fermeture, tous les références à celui-ci sont en train de changer .

essayer cette

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