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éesComment 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 }
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 }
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, 'someValue']) console.log(someIterator.next()) // { value: 123, done: false } console.log(someIterator.next()) // { value: 'someValue', done: false } console.log(someIterator.next()) // { value: undefined, done: true }
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, 'someValue'])
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 }
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] === 'function' } console.log(isIterator([11, 22, 33])) // true console.log(isIterator('sometring')) // 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
É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 }
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 = 'somestring' for (let item of str){ console.log(item) // s o m e s t r i n g }
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 = 'somestring' 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([['name', 'jenny'], ['id', 123]]) console.log(map) // Map { 'name' => '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
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 ] }
此外 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!