Question

Javascript (ECMAScript) prend en charge la méthode Array.prototype.forEach depuis la version 1.6 (édition 3 ECMAScript, 2005). Donc, beaucoup de navigateur déjà soutenir cette méthode et il est incroyablement rapide par rapport à la méthode $.each() jQuery par exemple.
(En fait, il bat toutes les implémentations, quelle que soit quelle bibliothèque Javascript)

Par rapport à jQuery, il est environ 60-70% plus rapide. Essayez-vous sur forEach vs jQuery sur JSPerf.

Le seul inconvénient que je l'ai jusqu'à présent l'utiliser est, je ne peux pas trouver un moyen de briser l'itération précoce. Comme for, while et do-while ont une déclaration de break, jQuerys .each() soutient les return false pour briser la boucle.

J'ai regardé dans les ECMAScript Edition 5 Spécifications (dernière je trouve), mais ils ne mentionnent pas une rupture anticipée de cette boucle.

Alors, la question, ce que M. Douglas Crockford appeler cela un design error
Suis-je manque quelque chose et il est possible de briser une telle boucle précoce?

Modifier

Merci pour les réponses à ce jour. Je suppose que puisque personne est venu avec une solution « native », il n'y a vraiment pas de mise en œuvre pour que (peut-être une fonctionnalité?). Quoi qu'il en soit, je ne sais vraiment pas comme les méthodes proposées donc je dupé autour d'un peu et a finalement trouvé que je aime (au moins, mieux). On dirait:

var div     = document.createElement('div'),
divStyle    = div.style,
support     = jQuery.support,
arr         = ['MozTransform', 'WebkitTransform', 'OTransform'];

arr.slice(0).forEach(function(v,i,a){    
    if(divStyle[v] === ''){
       support.transform = v;
       a.length = 0;
    }
});

est le code de production "réel". Je cherchais un moyen agréable de rechercher la css3 propriétés de transformation et je me suis perdu dans les specs de ecma5 et étranges forums Javascript: -)

Ainsi, vous pouvez passer l'objet de tableau lui-même en tant que troisième paramètre dans la fonction de rappel de .forEach. Je crée une copie du tableau original, appelant slice(0) et définir sa propriété .length à 0 dès que j'ai trouvé ce que je cherche. Fonctionne très bien.

Si quelqu'un arrive avec une meilleure solution que je vais modifier cela bien sûr.

Était-ce utile?

La solution

Eh bien, vous pouvez utiliser every à la place. La fonction est conçue pour revenir true si le retour de la fonction de rappel fournie true (truthy) pour chaque élément dans le tableau, et false autrement. Point clé ici est qu'une fois la fonction de rappel retourne une valeur falsly, every retourne sans false immediat itérer sur le reste du tableau. Donc ignorer la valeur de retour, et traiter every comme si elle était forEach.

[1, 2, 3, 4, 5].every(function(e) {
   alert(e);

   if (e > 2) return false; //break

   return true;
});

Dans cet exemple, alert ne se déclenche 3 fois.

Bien sûr, le grand Cavet ici est que vous devez retourner une valeur truthy si vous voulez que la boucle pour continuer. En fait, si vous revenez rien (non défini) la boucle s'arrête. Alternativly, vous pouvez utiliser some qui se comporte de la manière exactement inverse; retourne vrai lorsque la immediat fonction de rappel retourne une valeur truthy et fausse si elle ne fait jamais. Dans ce cas, return true serait votre déclaration « break ». Oui Backwards, mais il vous évite d'avoir à return true simplement avoir la boucle continue.

Maintenant, si vous concerened avec des performances, je voudrais recomend juste en utilisant une boucle de for normale, car il y a les frais généraux importants encourus lors de l'appel functionas qui ajouteront très rapidement avec des tableaux plus grands. L'utilisation des fonctions natives aide un peu, mais les frais généraux des appels répétés à des fonctions définies par l'utilisateur existe toujours et est non négligeable. Au moins cela a été mon expérience, vous devez bien sûr faire vos propres tests.

Autres conseils

Vous pourriez jeter une erreur de sortir de l'itération:

if (typeof BreakIteration == "undefined") {
  BreakIteration = new Error("BreakIteration");
}

try {
    [0,1,2,3,4].forEach(function(key, value) {            
        console.log(key + ': ' + value);

        if (value == 3) {
            throw BreakIteration;
        }
    });
} catch (error) {
    if (error !== BreakIteration) {
        throw error;
    }
}

Ce n'est pas exactement jolie. Je suis d'accord - bug spec

.

Je suppose que vous avez un morceau de code qui doit être exécuté contre chaque élément. Ne pas utiliser forEach pour trouver un élément ou même les opérations « arrêter au milieu ». Appliquer cette fonction à chaque élément dans un tableau.

Vous pourriez (je pense) utiliser une sorte d'indicateur global pour vérifier et faux retour si « trouvé » ou quelque chose.

var found = false;
array.forEach(function (k, v) { 
    if (found) 
    { 
        return false; 
    } 
    else 
    { 
        if (v == 1) 
        { 
            found = true; 
        }
    } 
}); 

Je pense que j'utiliser une autre construction si je veux faire une boucle de recherche.

Une option pour sortir du forEach-ing est bien sûr de quelque chose throw, mais il est pas vraiment une façon voudrait utiliser un jet ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top