L'itération est une méthode d'accès aux éléments de la collection ; les objets qui peuvent être itérés sont appelés objets itérables ; un itérateur est un objet qui peut mémoriser la position de traversée. L'objet itérateur commence à accéder à partir du premier élément de la collection jusqu'à ce que tous les éléments aient été accédés. , l'itérateur ne peut qu'avancer et non reculer.
L'évaluation paresseuse est souvent traduite par « évaluation paresseuse » ou « évaluation paresseuse », qui fait référence au calcul de la valeur d'une expression uniquement lorsqu'elle doit réellement être exécutée.
Le contraire de l'évaluation paresseuse est l'évaluation précoce, également connue sous le nom d'évaluation gourmande ou d'évaluation stricte, est la stratégie d'évaluation de la plupart des langages de programmation traditionnels.
Les avantages de tirer pleinement parti des caractéristiques de l'évaluation paresseuse se reflètent principalement dans les deux aspects suivants :
Éviter les calculs inutiles et améliorer les performances.
Économisez de l'espace et rendez possibles des structures de données en boucle infinie.
Les itérateurs dans ES6 permettent d'évaluer et de créer paresseusement des séquences de données définies par l'utilisateur. L'itération est un mécanisme de parcours de données. Un itérateur est un pointeur utilisé pour parcourir les éléments d'une structure de données (appelé Iterable), un pointeur utilisé pour produire une séquence de valeurs.
Un itérateur est un objet qui peut être itéré. Il fait abstraction du conteneur de données afin qu'il se comporte comme un objet itérable.
Les itérateurs ne calculent pas la valeur de chaque élément lorsqu'ils sont instanciés et génèrent uniquement la valeur suivante lorsque cela est demandé. Ceci est très utile, en particulier pour les grands ensembles de données ou les séquences d'éléments infinis.
Les objets itérables sont des structures de données qui souhaitent que leurs éléments soient accessibles publiquement. De nombreux objets en JS sont itérables. Ils peuvent ne pas être faciles à détecter, mais si vous examinez attentivement, vous trouverez les caractéristiques de l'itération :
new Map([iterable])
new WeakMap([ itérable] )
new Set([iterable])
new WeakSet([iterable])
Promise.all([iterable])
Promise.race([iterable])
Array.from([iterable])
nécessite également un objet itérable, sinon, il générera une erreur de type, par exemple :
for ... of
.. (opérateur d'expansion. )
const [a, b, ..] = itérable (affectation de déstructuration)
yield* (générateur)
Il existe de nombreux éléments itérables intégrés en JavaScript :
String,Array,TypedArray,Map ,Ensemble.
Les itérateurs et les objets itérables suivent le protocole d'itération.
Un protocole est un ensemble d'interfaces et précise comment les utiliser.
Les itérateurs suivent le protocole itérateur et les itérables suivent le protocole itérable.
Protocole itérable
Pour rendre un objet itérable, il doit implémenter une méthode itérateur via Symbol.iterator, qui est une usine pour les itérateurs.
En utilisant TypeScript, le protocole itérable ressemble à ceci :
interface Iterable { [Symbol.iterator]() : Iterator; }
Symbol.iterator]() est une fonction sans paramètre. L'appeler sur un objet itérable signifie que nous pouvons accéder à l'objet itérable via cela, qui peut être une fonction régulière ou une fonction génératrice.
Iterator Protocol
Le protocole itérateur définit une manière standard de produire une séquence de valeurs.
Pour qu'un objet soit un itérateur, il doit implémenter la méthode next(). Les itérateurs peuvent implémenter la méthode return(), dont nous parlerons plus loin dans cet article.
En utilisant TypeScript, le protocole de l'itérateur est le suivant :
interface Iterator { next() : IteratorResult; return?(value?: any): IteratorResult; }
IteratorResult est défini comme suit :
interface IteratorResult { value?: any; done: boolean; }
done informe le consommateur si l'itérateur a été utilisé, false signifie qu'il y a encore une valeur à générer, true signifie l'itérateur est terminé.
value peut être n'importe quelle valeur JS, c'est la valeur affichée au consommateur.
Lorsque cela est vrai, la valeur peut être omise.
Les itérateurs et les objets itérables peuvent être représentés par l'image suivante :
Les connaissances de base ont été introduites, puis utilisons quelques exemples pour approfondir notre image.
Range Iterator
Commençons par un itérateur très basique, l'itérateur createRangeIterator.
Nous appelons manuellement it.next() pour obtenir le prochain IteratorResult. Le dernier appel renvoie {done: true}, ce qui signifie que l'itérateur est désormais utilisé et ne produit plus de valeurs.
function createRangeIterator(from, to) { let i = from; return { next() { if (i <= to) { return { value: i++, done: false }; } else { return { done: true }; } } } } const it = createRangeIterator(1, 3); console.log(it.next()); console.log(it.next()); console.log(it.next()); console.log(it.next());
Iterable Range Iterator
Plus tôt dans cet article, j'ai mentionné que certaines instructions en JS nécessitent un objet itérable. Par conséquent, notre exemple précédent ne fonctionnera pas lorsqu’il est utilisé avec une boucle for...of.
Mais il est très facile de créer des objets conformes à l'itérateur et aux protocoles itérables.
function createRangeIterator (from, to) { let i = from return { [Symbol.iterator] () { return this }, next() { if (i <= to) { return { value: i++, done: false } } else { return { done: true } } } } } const it = createRangeIterator(1, 3) for (const i of it) { console.log(i) }
迭代器可以表示无限制大小的序列,因为它们仅在需要时才计算值。
注意不要在无限迭代器上使用扩展运算符(...),JS 将尝试消费迭代器,由于迭代器是无限的,因此它将永远不会结束。 所以你的应用程序将崩溃,因为内存已被耗尽
同样,for ... of 循环也是一样的情况,所以要确保能退出循环:
function createEvenNumbersIterator () { let value = 0 return { [Symbol.iterator] () { return this }, next () { value += 2 return { value, done: false} } } } const it = createEvenNumbersIterator() const [a, b, c] = it console.log({a, b, c}) const [x, y, z] = it console.log({ x, y, z }) for (const even of it) { console.log(even) if (even > 20) { break } }
关闭迭代器
前面我们提到过,迭代器可以有选择地使用return()方法。 当迭代器直到最后都没有迭代时使用此方法,并让迭代器进行清理。
for ... of循环可以通过以下方式更早地终止迭代:
break
continue
throw
return
function createCloseableIterator () { let idx = 0 const data = ['a', 'b', 'c', 'd', 'e'] function cleanup() { console.log('Performing cleanup') } return { [Symbol.iterator]() { return this }, next () { if (idx <= data.length - 1) { return { value: data[idx++], done: false } } else { cleanup() return { done: true } } }, return () { cleanup() return { done: true } } } } const it = createCloseableIterator() for (const value of it) { console.log(value) if (value === 'c') { break } } console.log('\n----------\n') const _it = createCloseableIterator(); for (const value of _it) { console.log(value); }
如果知道迭代器已经结束,则手动调用cleanup()函数。
如果突然完成,则return()起作用并为我们进行清理。
【推荐学习:javascript高级教程】
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!