2009-09-29 7 views
2

Ceci est si simple que je suis déconcerté. Je donne les résultats suivants:JavaScript Array Iteration retournant plus que des valeurs

var x = 'shrimp';  
var stypes = new Array('shrimp', 'crabs', 'oysters', 'fin_fish', 'crawfish', 'alligator'); 
for (t in stypes) { 
    if (stypes[t] != x) { 
     alert(stypes[t]); 
    } 
} 

Une fois les valeurs itérées il commence à renvoyer une douzaine de fonctions comme

function (iterator, context) { 
    var index = 0; 
    iterator = iterator.bind(context); 
    try { 
     this._each(function (value) {iterator(value, index++);}); 
    } catch (e) { 
     if (e != $break) { 
      throw e; 
     } 
    } 
    return this; 
} 

Que diable se passe? Edit: Dans ces scripts j'utilise http://script.aculo.us/prototype.js et http://script.aculo.us/scriptaculous.js Je me souviens maintenant de lire sur la façon dont le prototype étend les tableaux et je parie que cela en fait partie. Comment puis-je y faire face?

+0

J'étais sur le point de dire ... que le code fonctionne bien pour moi, quelque chose doit avoir prototypé Array différemment. J'irais avec la réponse de Quintin. – womp

Répondre

7

L'énumération for va aller sur chaque membre de l'objet que vous lui avez transmis. Dans ce cas, un tableau, qui a des fonctions en tant que membres ainsi que les éléments passés.

Vous pouvez réécrire votre boucle for pour vérifier si typeof stypes[t] == "function" ou yada yada. Mais l'OMI vous êtes mieux juste de modifier votre mise en boucle à des éléments seulement ..

for(var i = 0, t; t = stypes[i]; ++i){ 
    if (t != x) { 
     alert(t); 
    } 
} 

Ou

for(var i = 0; i < stypes.length; ++i){ 
    if (stypes[i] != x) { 
     alert(stypes[i]); 
    } 
} 

Je voulais migrer mon dernier commentaire à la réponse à ajouter l'avis de mise en garde pour une le premier type de boucle.

de Simon Willison's "A re-introduction to JavaScript" ..

for (var i = 0, item; item = a[i]; i++) { 
    // Do something with item 
} 

Nous sommes ici la mise en place de deux variables. L'affectation dans la partie médiane de la boucle for est également testé pour véracité - si elle réussit, la boucle continue. Comme i est incrémenté à chaque fois, les articles du tableau seront affectés à l'article dans l'ordre séquentiel . La boucle s'arrête lorsqu'un élément "falsifié" est trouvé (tel que non défini).

Notez que cette astuce ne doit être utilisé pour les tableaux que vous ne le savez pas contiennent « falsy » valeurs (tableaux de objets ou DOM noeuds par exemple). Si vous êtes en train d'itérer sur des données numériques qui pourraient inclure un 0 ou des données de chaîne qui pourraient inclure la chaîne vide , vous devriez utiliser le i, j idiom à la place.

+1

Toute explication pour le downvote, je suis très intéressé par la raison pour cela. –

+0

Juste pour ajouter à votre bonne réponse: '" for..in "' rampe la chaîne 'Array.prototype'. Voir http://www.ecma-international.org/publications/standards/Ecma-262.htm (Sec 12.6.4), alors qu'une boucle 'for' standard ne le fait pas. De même, l'ordre des éléments itérés avec "for..in" n'est pas garanti. Une boucle 'for' standard est. –

+0

Cela a fonctionné pour moi. Je vous ai remis à zéro. Je ne suis pas familier avec cette syntaxe dans for() pour (var i = 0, t; Qu'est-ce que cela s'appelle? – jerrygarciuh

-3

Il devrait être

for (t in stypes) { 
    if (t != x) { 
     alert(t); 
    } 
} 
3

que vous voulez faire:

for (var i in object) { 
    if (!object.hasOwnProperty(i)) 
     continue; 
    ... do stuff ... 
} 

Comme itère énumération for..in sur toutes les propriétés (dénombrables ou autrement) qui existent à la fois l'objet et sa chaîne prototype. La vérification hasOwnProperty restreint l'itération aux seules propriétés de l'objet réel que vous souhaitez énumérer.

ES5 rend les choses un peu mieux pour les développeurs de la bibliothèque (et aider à éviter ce genre de choses), mais nous ne verrons pas ce navigateur d'expédition ina pour un certain temps :-(

[edit:. Remplaçant le retour à continuer lalalalala ;)]

+0

Vous voulez 'continuer;', pas 'return;'. – ThiefMaster

1

Puisque le prototype a étendu le tableau pour votre commodité, vous devriez en profiter. Votre exemple pourrait être réécrit comme:

var x = 'shrimp';  
var stypes = new Array('shrimp', 'crabs', 'oysters', 'fin_fish', 'crawfish', 'alligator'); 
stypes.without(x).each(alert);