2009-04-23 5 views
2

J'ai été surpris de pouvoir reproduire un bug avec un minimum de code. Notez que dans cet exemple minimaliste, Array.indexOf n'est pas appelé. Notez également que j'ai essayé plusieurs implémentations différentes d'indexOf, dont plusieurs de stackoverflow.com.Quelle est la cause de cette erreur avec for ... in après l'affectation de Array.prototype.indexOf?

Le bug est, lorsque le for ... in s'exécute dans IE, trois alertes sont affichées: "indexOf", "0" et "1". En FF, comme on pouvait s'y attendre, seulement deux ("0", "1") apparaissent.

<html> 
<body onLoad="test();"> 
<script language="javascript"> 
    var testArray = ['Foo', 'Bar']; 

    if(!Array.prototype.indexOf) { 
     Array.prototype.indexOf = function (obj, fromIndex) { 
     if (fromIndex == null) { 
      fromIndex = 0; 
     } else if (fromIndex < 0) { 
      fromIndex = Math.max(0, this.length + fromIndex); 
     } 
     for (var i = fromIndex, j = this.length; i < j; i++) { 
      if (this[i] === obj) 
       return i; 
     } 
     return -1; 
     }; 
    } 

    function test() { 
     var i; 

     for(i in testArray) { 
     alert(i); 
     } 
    } 
</script> 
</body> 
</html> 

Quelqu'un peut-il expliquer cela? J'ai déjà changé mon code pour utiliser un while donc je ne suis pas sous le feu, mais celui-ci m'a vraiment perplexe. Cela me rappelle des erreurs de dépassement de mémoire dans c.

Répondre

4

Voir "for in Intrigue" sur Yahoo! Blog de l'interface utilisateur.

La raison pour laquelle votre code fonctionne comme prévu dans Firefox est que vous n'avez pas ajouté votre propre méthode indexOf dans Firefox. La boucle for in parcourt toutes les clés de la chaîne prototype de l'objet, y compris la méthode indexOf que vous avez ajoutée. Douglas Crockford propose la solution suivante:

for (var p in testArray) { 
    if (testArray.hasOwnProperty(p)) { 
     alert(testArray[i]); 
    } 
} 

Vous pouvez simplement filtrer les fonctions:

for (var p in testArray) { 
    if (typeof testArray[p] !== "function") { 
     alert(testArray[i]); 
    } 
} 

aussi, comme « nickf », souligne, il est préférable de ne pas utiliser la boucle for in pour itérer sur les tableaux. La boucle for in est destinée à l'itération sur les clés d'un objet.

Steve

+0

Merci beaucoup; c'est exactement ce dont j'avais besoin. – overslacked

+0

Vous ne devriez vraiment pas utiliser pour ... sur des tableaux du tout. Voir le lien dans ma réponse. – nickf

+0

@Steve: Comme il n'y a rien de cassé, je n'appellerais pas en utilisant "hasOwnProperty()" un correctif. ;-) – Tomalak

4

for .. in est conçu pour une boucle à travers des propriétés d'objet, certainement pas des tableaux.

bâton à la norme:

for (var i = 0, l = myArray.length; i < l; ++i) { .. } 

Plus d'infos sur le Mozilla Developer Centre:

Une boucle for...in n'itérer pas plus propriétés intégrées. Cela inclut toutes les méthodes intégrées d'objets, telles que la méthode indexOf de String ou la méthode toString de l'objet. Cependant, la boucle parcourra toutes les propriétés définies par l'utilisateur (y compris celles qui écrasent les propriétés intégrées).

Bien qu'il puisse être tentant de l'utiliser comme un moyen d'itérer sur un tableau, c'est une mauvaise idée. L'instruction for ... in itère sur les propriétés définies par l'utilisateur en plus des éléments du tableau, donc si vous modifiez les propriétés non entières ou non positives du tableau (par exemple en lui ajoutant une propriété "foo" ou même en ajoutant un méthode ou propriété à Array.prototype), l'instruction for ... in renverra le nom de vos propriétés définies par l'utilisateur en plus des index numériques.

+0

Comme je l'ai mentionné dans la question, il s'agit d'un exemple minimaliste qui ne fait que reproduire le problème; mais votre point de vue est bon. – overslacked

+0

Juste pour m'assurer que je donne des crédits appropriés, votre réponse était exacte à 100%; mais c'était l'information initiale fournie dans la réponse de Steve concernant pourquoi le problème se produisait de tout ce dont j'avais besoin. Merci pour l'aide! – overslacked

Questions connexes