Des lecteurs comme vous aident à soutenir MUO. Lorsque vous effectuez un achat en utilisant des liens sur notre site, nous pouvons gagner une commission d'affiliation. En savoir plus.

Itérer sur des collections de données à l'aide de boucles traditionnelles peut rapidement devenir fastidieux et lent, en particulier lorsqu'il s'agit de quantités massives de données.

Les générateurs et les itérateurs JavaScript fournissent une solution pour itérer efficacement sur de grandes collections de données. En les utilisant, vous pouvez contrôler le flux d'itération, produire des valeurs une par une, et mettre en pause et reprendre le processus d'itération.

Ici, vous couvrirez les bases et les éléments internes d'un itérateur JavaScript et comment vous pouvez générer un itérateur manuellement et à l'aide d'un générateur.

Itérateurs JavaScript

Un itérateur est un objet JavaScript qui implémente le protocole itérateur. Ces objets le font en ayant un suivant méthode. Cette méthode retourne un objet qui implémente le IteratorResultIteratorResultIteratorResult interface.

instagram viewer

Le IteratorResultIteratorResultIteratorResult interface comprend deux propriétés: fait et valeur. Le fait propriété est un booléen qui renvoie FAUX si l'itérateur peut produire la valeur suivante dans sa séquence ou vrai si l'itérateur a terminé sa séquence.

Le valeur propriété est une valeur JavaScript renvoyée par l'itérateur lors de sa séquence. Lorsqu'un itérateur termine sa séquence (quand faitvrai), cette propriété renvoie indéfini.

Comme leur nom l'indique, les itérateurs vous permettent de "itérer" sur des objets JavaScript tels que des tableaux ou des cartes. Ce comportement est possible grâce au protocole itérable.

En JavaScript, le protocole itérable est un moyen standard de définir des objets sur lesquels vous pouvez itérer, comme dans un pour... de boucle.

Par exemple:

constante fruits = ["Banane", "Mangue", "Pomme", "Raisins"];

pour (constante itérateur de des fruits) {
console.log (itérateur);
}

/*
Banane
mangue
Pomme
Raisins
*/

Cet exemple itère sur le des fruits tableau à l'aide d'un pour... de boucle. À chaque itération, il enregistre la valeur actuelle dans la console. Ceci est possible car les tableaux sont itérables.

Certains types JavaScript, tels que les tableaux, les chaînes, Ensembles et cartes, sont des itérables intégrés car ils (ou l'un des objets de leur chaîne de prototypes) implémentent un @@itérateur méthode.

D'autres types, tels que les objets, ne sont pas itérables par défaut.

Par exemple:

constante iterObjet = {
voitures: [" Tesla ", "BMW", "Toyote"],
animaux: ["Chat", "Chien", "Hamster"],
nourriture: ["Burgers", "Pizza", "Pâtes"],
};

pour (constante itérateur de iterObjet) {
console.log (itérateur);
}

// TypeError: iterObject n'est pas itérable

Cet exemple montre ce qui se passe lorsque vous essayez d'itérer sur un objet qui n'est pas itérable.

Rendre un objet itérable

Pour rendre un objet itérable, vous devez implémenter un Symbole.itérateur méthode sur l'objet. Pour devenir itérable, cette méthode doit retourner un objet qui implémente le IteratorResultIteratorResultIteratorResult interface.

Le Symbole.itérateur symbole a le même but que @@itérateur et peuvent être utilisés de manière interchangeable dans "spécification" mais pas dans le code comme @@itérateur n'est pas une syntaxe JavaScript valide.

Les blocs de code ci-dessous fournissent un exemple de la façon de rendre un objet itérable en utilisant le iterObjet.

Tout d'abord, ajoutez le Symbole.itérateur méthode pour iterObjet en utilisant une fonction déclaration.

Ainsi:

iterObjet[Symbole.itérateur] = fonction () {
// Les blocs de code suivants vont ici...
}

Ensuite, vous devrez accéder à toutes les clés de l'objet que vous souhaitez rendre itérable. Vous pouvez accéder aux clés à l'aide du Object.keys, qui renvoie un tableau des propriétés énumérables d'un objet. Pour retourner un tableau de iterObjet, passez les ce mot-clé comme argument de Object.keys.

Par exemple:

laisser objPropriétés = Objet.clés(ce)

L'accès à ce tableau vous permettra de définir le comportement d'itération de l'objet.

Ensuite, vous devez suivre les itérations de l'objet. Vous pouvez y parvenir en utilisant des variables de compteur.

Par exemple:

laisser propriétéIndex = 0;
laisser index_enfant = 0;

Vous utiliserez la première variable de compteur pour suivre les propriétés de l'objet et la seconde pour suivre les enfants de la propriété.

Ensuite, vous devrez implémenter et retourner le suivant méthode.

Ainsi:

retour {
suivant() {
// Les blocs de code suivants vont ici...
}
}

À l'intérieur de suivant, vous devrez gérer un cas limite qui se produit lorsque l'intégralité de l'objet a été itérée. Pour gérer le cas limite, vous devez retourner un objet avec le valeur mis à indéfini et fait mis à vrai.

Si ce cas n'est pas géré, essayer d'itérer sur l'objet entraînera une boucle infinie.

Voici comment gérer le cas marginal :

si (propriétéIndex > objPropriétés.longueur- 1) {
retour {
valeur: indéfini,
fait: vrai,
};
}

Ensuite, vous devrez accéder aux propriétés de l'objet et à leurs éléments enfants à l'aide des variables de compteur que vous avez déclarées précédemment.

Ainsi:

// Accéder aux propriétés parent et enfant
constante propriétés = ce[objProperties[propertyIndex]] ;

constante propriété = propriétés[indiceenfant] ;

Ensuite, vous devez implémenter une logique pour incrémenter les variables de compteur. La logique doit réinitialiser le indexenfant lorsqu'il n'existe plus d'éléments dans le tableau d'une propriété et passer à la propriété suivante dans l'objet. De plus, il devrait augmenter indexenfant, s'il y a encore des éléments dans le tableau de la propriété actuelle.

Par exemple:

// Logique d'incrémentation d'index
if (childIndex >= properties.length - 1) {
// s'il n'y a plus d'éléments dans le tableau enfant
// réinitialiserenfantindice
indexenfant = 0 ;

// Passe à la propriété suivante
propriétéIndex++ ;
} autre {
// Passe à l'élément suivant dans le tableau enfant
indexenfant++
}

Enfin, retournez un objet avec le fait propriété définie sur FAUX et le valeur propriété définie sur l'élément enfant actuel dans l'itération.

Par exemple:

retour {
fait: FAUX,
valeur: propriété,
};

Votre terminé Symbole.itérateur la fonction doit être similaire au bloc de code ci-dessous :

iterObjet[Symbole.itérateur] = fonction () {
constante objPropriétés = Objet.clés(ce);
laisser propriétéIndex = 0;
laisser index_enfant = 0;

retour {
suivant: () => {
//Traitement du cas limite
si (propriétéIndex > objPropriétés.longueur- 1) {
retour {
valeur: indéfini,
fait: vrai,
};
}

// Accéder aux propriétés parent et enfant
constante propriétés = ce[objProperties[propertyIndex]] ;

constante propriété = propriétés[indiceenfant] ;

// Logique d'incrémentation d'index
if (childIndex >= properties.length - 1) {
// s'il n'y a plus d'éléments dans le tableau enfant
// réinitialiserenfantindice
indexenfant = 0 ;

// Passe à la propriété suivante
propriétéIndex++ ;
} autre {
// Passe à l'élément suivant dans le tableau enfant
indexenfant++
}

retour {
fait: FAUX,
valeur: propriété,
};
},
};
};

Exécution d'un pour... de boucle sur iterObjet après cette implémentation ne générera pas d'erreur car il implémente un Symbole.itérateur méthode.

L'implémentation manuelle des itérateurs, comme nous l'avons fait ci-dessus, n'est pas recommandée car elle est très sujette aux erreurs et la logique peut être difficile à gérer.

Générateurs JavaScript

Un générateur JavaScript est une fonction que vous pouvez mettre en pause et reprendre son exécution à tout moment. Ce comportement lui permet de produire une séquence de valeurs dans le temps.

Une fonction générateur, qui est une fonction qui renvoie un générateur, offre une alternative à la création d'itérateurs.

Vous pouvez créer une fonction de générateur de la même manière que vous créeriez une déclaration de fonction en JavaScript. La seule différence est que vous devez ajouter un astérisque (*) au mot-clé de la fonction.

Par exemple:

fonction* exemple () {
retour"Générateur"
}

Lorsque vous appelez une fonction normale en JavaScript, elle renvoie la valeur spécifiée par son retour mot clé ou indéfini sinon. Mais une fonction génératrice ne renvoie aucune valeur immédiatement. Elle renvoie un objet Generator, que vous pouvez affecter à une variable.

Pour accéder à la valeur courante de l'itérateur, appelez la suivant méthode sur l'objet Generator.

Par exemple:

constante gen = exemple();

console.log (gen.next()); // { valeur: 'Générateur', fait: vrai }

Dans l'exemple ci-dessus, le valeur la propriété provenait d'un retour mot-clé, mettant effectivement fin au générateur. Ce comportement est généralement indésirable avec les fonctions de générateur, car ce qui les distingue des fonctions normales est la possibilité de suspendre et de redémarrer l'exécution.

Le rendement

Le rendement Le mot-clé fournit un moyen de parcourir les valeurs dans les générateurs en interrompant l'exécution d'une fonction de générateur et en renvoyant la valeur qui la suit.

Par exemple:

fonction* exemple() {
rendement"Des modèles"
rendement"Modèle X"
rendement"Cybercamion"

retour" Tesla "
}

constante gen = exemple();

console.log (gen.next()); // { valeur: 'Des modèles', fait: FAUX }

Dans l'exemple ci-dessus, lorsque le suivant méthode est appelée sur le exemple générateur, il s'arrêtera à chaque fois qu'il rencontrera le rendement mot-clé. Le fait la propriété sera également définie sur FAUX jusqu'à ce qu'il rencontre un retour mot-clé.

Appelant le suivant méthode plusieurs fois sur le exemple générateur pour le démontrer, vous aurez ce qui suit comme sortie.

console.log (gen.next()); // { valeur: 'Modèle X', fait: FAUX }
console.log (gen.next()); // { valeur: "Cybercamion", fait: FAUX }
console.log (gen.next()); // { valeur: "Tesla", fait: vrai }

console.log (gen.next()); // { valeur: non défini, terminé: vrai }

Vous pouvez également itérer sur un objet Generator à l'aide de la commande pour... de boucle.

Par exemple:

pour (constante itérateur de gén) {
console.log (itérateur);
}

/*
Des modèles
Modèle X
Cyber-camion
*/

Utiliser des itérateurs et des générateurs

Bien que les itérateurs et les générateurs puissent sembler être des concepts abstraits, ils ne le sont pas. Ils peuvent être utiles lorsque vous travaillez avec des flux de données et des collections de données infinis. Vous pouvez également les utiliser pour créer des identifiants uniques. Les bibliothèques de gestion d'état telles que MobX-State-Tree (MST) les utilisent également sous le capot.