Maison > interface Web > js tutoriel > le corps du texte

Introduction aux principes des itérateurs et des objets itérables dans ES6 (avec exemples)

不言
Libérer: 2018-10-29 15:34:36
avant
2616 Les gens l'ont consulté

Cet article vous apporte une introduction aux principes des itérateurs et des objets itérables dans ES6 (avec des exemples). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Les nouvelles méthodes de tableau, collections, boucles for-of, opérateurs de propagation (...) et même la programmation asynchrone d'ES6 reposent tous sur l'implémentation d'un itérateur (Iterator). Cet article expliquera en détail les itérateurs et les générateurs d'ES6, et explorera plus en détail les principes internes et l'utilisation des objets itérables

1 Le principe des itérateurs

Traitement des tableaux dans les langages de programmation. Lorsque vous utilisez une instruction de boucle ou une collection, vous devez initialiser une variable pour enregistrer la position de l'itération, et l'utilisation d'itérateurs par programme peut simplifier cette opération de données

Comment concevoir un itérateur ?

L'itérateur lui-même est un objet. Cet objet a la méthode next() pour renvoyer l'objet résultat. Cet objet résultat a la valeur de retour suivante et la valeur booléenne de fin d'itération effectuée, qui simule le résultat. création d'un itérateur simple Comme suit :

function createIterator(iterms) {
  let i = 0
  return {
    next() {
      let done = (i >= iterms.length)
      let value = !done ? iterms[i++] : undefined
      return {
        done,
        value
      }
    }
  }
}

let arrayIterator = createIterator([1, 2, 3])

console.log(arrayIterator.next()) // { done: false, value: 1 }
console.log(arrayIterator.next()) // { done: false, value: 2 }
console.log(arrayIterator.next()) // { done: false, value: 3 }
console.log(arrayIterator.next()) // { done: true, value: undefined }
Copier après la connexion
Si vous êtes confus sur la syntaxe ci-dessus, vous pouvez vous référer à : Explication détaillée des nouvelles fonctions des objets et affectation de déstructuration dans ES6 (exemples de code)

Next (de chaque appel à l'itérateur) renverra l'objet suivant jusqu'à ce que l'ensemble de données soit épuisé.

Les règles d'écriture des itérateurs dans ES6 sont similaires, mais des objets générateurs sont introduits, ce qui facilite la création d'objets itérateurs

2. Créer des itérateurs

ES6 encapsule un générateur pour créer des itérateurs. Évidemment, un générateur est une fonction qui renvoie un itérateur, qui est représenté par un astérisque (*) après la fonction, et utilise le nouveau mot-clé spécial interne rendement pour spécifier la valeur de retour de la méthode next() de l'itérateur.

Comment créer un itérateur à l'aide des générateurs ES6 ? Un exemple simple est le suivant :

function *createIterator() {
  yield 123;
  yield 'someValue'
}

let someIterator = createIterator()

console.log(someIterator.next()) // { value: 123, done: false }
console.log(someIterator.next()) // { value: 'someValue', done: false }
console.log(someIterator.next()) // { value: undefined, done: true }
Copier après la connexion

L'utilisation du mot-clé rendement peut renvoyer n'importe quelle valeur ou expression, et vous pouvez ajouter des éléments à l'itérateur par lots :

// let createIterator = function *(items) { // 生成器函数表达式
function *createIterator(items) {
  for (let i = 0; i < items.length; i++) {
    yield items[i]
  }
}

let someIterator = createIterator([123, &#39;someValue&#39;])

console.log(someIterator.next()) // { value: 123, done: false }
console.log(someIterator.next()) // { value: &#39;someValue&#39;, done: false }
console.log(someIterator.next()) // { value: undefined, done: true }
Copier après la connexion

Depuis le générateur elle-même est une fonction, elle peut donc être ajoutée à l'objet et utilisée comme suit :

let obj = {
  // createIterator: function *(items) { // ES5
  *createIterator(items) { // ES6
    for (let i = 0; i < items.length; i++) {
      yield items[i]
    }
  }
}
let someIterator = obj.createIterator([123, &#39;someValue&#39;])
Copier après la connexion
Une caractéristique de la fonction génératrice est qu'après l'exécution d'une instruction rendement, la fonction cessera automatiquement de s'exécuter et la méthode next() de l'itérateur sera appelé à nouveau. Continuez l'exécution avec la prochaine instruction de rendement.
Cette capacité à abandonner automatiquement l'exécution d'une fonction conduit à de nombreuses utilisations avancées.

3. Objets itérables

Les objets de collection couramment utilisés (tableaux, collections Set/Map) et les chaînes dans ES6 sont des objets itérables, et ces objets ont des itérateurs par défaut et le Symbol.iterator. propriété.

Les itérateurs créés via des générateurs sont également des objets itérables, car les générateurs attribuent des valeurs à la propriété Symbol.iterator par défaut.

3.1 Symbol.iterator

Les objets itérables ont la propriété Symbol.iterator, c'est-à-dire que les objets avec la propriété Symbol.iterator ont des itérateurs par défaut.

On peut utiliser Symbol.iterator pour accéder à l'itérateur par défaut d'un objet, par exemple pour un tableau :

let list = [11, 22, 33]
let iterator = list[Symbol.iterator]()
console.log(iterator.next()) // { value: 11, done: false }
Copier après la connexion

Symbol.iterator obtient l'itérateur par défaut de l'objet itérable du tableau, et L'opération parcourt les éléments du tableau.

Au contraire, nous pouvons utiliser Symbol.iterator pour détecter si l'objet est un objet itérable :

function isIterator(obj) {
  return typeof obj[Symbol.iterator] === &#39;function&#39;
}

console.log(isIterator([11, 22, 33])) // true
console.log(isIterator(&#39;sometring&#39;)) // true
console.log(isIterator(new Map())) // true
console.log(isIterator(new Set())) // true
console.log(isIterator(new WeakMap())) // false
console.log(isIterator(new WeakSet())) // false
Copier après la connexion

Évidemment, les tableaux, les collections Set/Map et les chaînes sont tous des objets itérables, et les collections WeakSet /WeakMap (collections de référence faibles) ne sont pas itérables.

3.2 Création d'objets itérables

Par défaut, les objets personnalisés ne sont pas itérables.

Comme mentionné tout à l'heure, l'itérateur créé via le générateur est également un objet itérable. Le générateur attribuera une valeur à la propriété Symbol.iterator par défaut.

Alors comment transformer un objet personnalisé en un objet itérable ? En ajoutant un générateur à la propriété Symbol.iterator :

let collection = {
  items: [11,22,33],
  *[Symbol.iterator]() {
    for (let item of this.items){
      yield item
    }
  }
}

console.log(isIterator(collection)) // true

for (let item of collection){
  console.log(item) // 11 22 33
}
Copier après la connexion

Les éléments du tableau sont un objet itérable, et l'objet de collection devient également un objet itérable en attribuant une valeur à la propriété Symbol.iterator.

3.3 for-of

Remarquez que le dernier châtaigne utilise for-of au lieu de la boucle d'index for-of est une nouvelle fonctionnalité ajoutée par ES6 pour les objets itérables.

Pensez au principe de mise en œuvre de la boucle for-of.

Pour les objets itérables utilisant for-of, chaque fois que for-of est exécuté, next() de l'objet itérable sera appelé, et le résultat renvoyé sera stocké dans une variable, et l'exécution se poursuivra jusqu'à ce que le objet itérable La valeur de l'attribut done est fausse.

// 迭代一个字符串
let str = &#39;somestring&#39;

for (let item of str){
  console.log(item) // s o m e s t r i n g
}
Copier après la connexion

Essentiellement, for-of appelle la méthode de propriété Symbol.iterator de la chaîne str pour obtenir l'itérateur (ce processus est complété par le moteur JS), puis appelle la méthode next() plusieurs fois pour modifier la valeur de l'objet Stocké dans la variable d'élément.

L'utilisation de for-of pour des objets non itérables, nuls ou indéfinis signalera une erreur !

3.4 Opérateur de propagation (...)

L'opérateur de propagation de sucre syntaxique ES6 (...) sert également des objets itérables, c'est-à-dire qu'il ne peut "étaler" que des tableaux, des collections , chaînes, objets itérables personnalisés.

Les exemples suivants génèrent les résultats calculés par les opérateurs de propagation de différents objets itérables :

let str = &#39;somestring&#39;
console.log(...str) // s o m e s t r i n g
let set = new Set([1, 2, 2, 5, 8, 8, 8, 9])
console.log(set) // Set { 1, 2, 5, 8, 9 }
console.log(...set) // 1 2 5 8 9
let map = new Map([[&#39;name&#39;, &#39;jenny&#39;], [&#39;id&#39;, 123]])
console.log(map) // Map { &#39;name&#39; => 'jenny', 'id' => 123 }
console.log(...map) // [ 'name', 'jenny' ] [ 'id', 123 ]
let num1 = [1, 2, 3], num2 = [7, 8, 9]
console.log([...num1, ...num2]) // [ 1, 2, 3, 7, 8, 9 ]
let udf
console.log(...udf) // TypeError: undefined is not iterable
Copier après la connexion

Comme le montre le code ci-dessus, l'opérateur de propagation (...) peut facilement convertir les objets itérables en objet converti en tableau. Comme for-of, l'opérateur spread (...) signalera une erreur lorsqu'il est utilisé sur des objets non itérables, nuls ou indéfinis !

4. Itérateur par défaut

ES6 为很多内置对象提供了默认的迭代器,只有当内建的迭代器不能满足需求时才自己创建迭代器。

ES6 的 三个集合对象:Set、Map、Array 都有默认的迭代器,常用的如values()方法、entries()方法都返回一个迭代器,其值区别如下:

entries():多个键值对

values():集合的值

keys():集合的键

调用以上方法都可以得到集合的迭代器,并使用for-of循环,示例如下:

/******** Map ***********/
let map = new Map([['name', 'jenny'], ['id', 123]])

for(let item of map.entries()){
  console.log(item) // [ 'name', 'jenny' ]  [ 'id', 123 ]
}
for(let item of map.keys()){
  console.log(item) // name id
}
for (let item of map.values()) {
  console.log(item) // jenny 123
}

/******** Set ***********/
let set = new Set([1, 4, 4, 5, 5, 5, 6, 6,])

for(let item of set.entries()){
  console.log(item) // [ 1, 1 ] [ 4, 4 ] [ 5, 5 ] [ 6, 6 ]
}

/********* Array **********/
let array = [11, 22, 33]

for(let item of array.entries()){
  console.log(item) // [ 0, 11 ] [ 1, 22 ] [ 2, 33 ]
}
Copier après la connexion

此外 String 和 NodeList 类型都有默认的迭代器,虽然没有提供其它的方法,但可以用for-of循环

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!

Étiquettes associées:
source:segmentfault.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal