2010-09-22 8 views
1

Je possède ce code dans la fonction de la réussite d'un appel ajax jQuery success: function(d)Appel d'une fonction dans une fonction javascript

for (var n in d.items) 
{   
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() { 
     focusMarker(d.items[n].id); 
    }); 
} 

Malheureusement, la fonction toujours évaluée d.items[n].id comme le dernier élément de collection d.items.

J'ai essayé de faire cette modification:

for (var n in d.items) 
{   
    var id = d.items[n].id;   
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() { 
     focusMarker(id); 
    }); 
} 

mais ma fonction retourne toujours la même chose.

Est-ce un problème d'étendue ou y a-t-il un problème avec ma définition de fonction?

Répondre

6

Il y a plusieurs façons de résoudre ce problème est d'utiliser une fonction pour préserver les valeurs de mise en boucle les plus courantes:

for (var n in d.items) { 
    (function(id) { 
    google.maps.event.addListener(markers[id], 'mouseover', function() { 
     focusMarker(id); 
    }); 
    })(d.items[n].id); 
} 

Par ailleurs, si d.items est un tableau, je vous recommande d'utiliser une boucle séquentielle par exemple:

for (var n = 0; n < d.items.length; n++) { 
    //.. 
} 

La déclaration for-in est destiné à être utilisé pour énumèrent sur des propriétés d'objet. Si vous l'utilisez sur des tableaux ou des objets de type tableau, cela peut vous poser plusieurs problèmes. Premièrement, les propriétés héritées sont également énumérées, ce qui signifie que si quelqu'un augmente l'objet Array.prototype, ces propriétés seront également énumérées dans votre boucle.

Aussi l'ordre d'itération n'est pas garantie par la spécification, les propriétés peuvent ne pas être visitées dans l'ordre numérique.

+0

Merci, cela a fonctionné parfaitement! – Zahymaka

1

Vous pouvez faire une fermeture:

for (var n in d.items) 
{   
    (function(id) {   
     google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() { 
      focusMarker(id); 
     }); 
    })(d.items[n].id) 
} 
1

Ceci est un problème de portée. Ce que vous voulez faire est d'utiliser une fermeture comme ceci:

for (var n in d.items) 
{   
    (function(id){ 
     google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() { 
      focusMarker(id); 
     }); 
    })(d.items[n].id); 
} 
1

Oui, il y a un problème de portée et a very common one.

variables enfermées dans une fermeture partagent le même environnement unique, donc au moment où le rappel mouseover est appelée, la boucle for in aura suivi son cours, et la variable n sera pointera à la dernière valeur, il a été affecté.

Vous pouvez résoudre ce problème avec encore plus de fermetures, en utilisant une usine de fonction:

function makeOnHoverHandler(id) { 
    return function() { 
    focusMarker(id); 
    }; 
} 

// ... 

for (var n in d.items) {   
    google.maps.event.addListener(markers[d.items[n].id], 
           'mouseover', 
           makeOnHoverHandler(d.items[n].id)); 
} 

Cela peut être un sujet très délicat, si vous n'êtes pas familier avec le fonctionnement des fermetures. Vous pouvez consulter l'article suivant Mozilla pour une brève introduction:

Vous pouvez également inline ci-dessus.Ceci est en fait une approche plus commune, mais est pratiquement le même que ci-dessus:

for (var n in d.items) {   
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', (function (id) { 
    focusMarker(id); 
    })(d.items[n].id)); 
} 

Toute autre solution consiste à enfermer chaque itération dans sa propre portée, en utilisant l'auto invoquant des fonctions anonymes:

for (var n in d.items) { 
    (function (id) { 
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() { 
     focusMarker(id); 
    }); 
    })(d.items[n].id); 
} 
1

similaires à d'autres réponses, mais je pense que la définition en ligne des choses est plus propre, un style plus concis:

for (var n in d.items) 
{   
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', new function() { 
     return function() { 
      focusMarker(d.items[n].id); 
     } 
    }); 
} 

Vous pourriez vous demander ce que new function() fait. Cela déclare et exécute une fonction tout à la fois. Il est essentiellement un raccourci pour:

for (var n in d.items) 
{   
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() { 
     return function() { 
      focusMarker(d.items[n].id); 
     } 
    }()); 
} 

Bien que je pense que deuxième exemple ne fonctionne pas, parce que si vous n'êtes pas attribuer le résultat à une variable dont vous avez besoin entre parenthèses supplémentaires. Par exemple:

function() { alert("hi"); }(); 

est une erreur de syntaxe. A être:

(function() { alert("hi"); })(); 

Est en ligne comme argument de fonction count comme mission? Je ne sais pas. Mieux vaut mon premier exemple.

Questions connexes