Cet article vous présente principalement le résumé d'apprentissage de l'utilisation de l'itérateur ES6 (Iterator) et de la boucle for.of. L'éditeur pense qu'il est plutôt bon, je vais donc le partager avec vous maintenant et le donner comme référence. Suivons l'éditeur pour y jeter un œil, j'espère que cela pourra aider tout le monde.
1. Qu'est-ce qu'un itérateur ?
Le concept de générateur est disponible en Java, Python et d'autres langages, et ES6 a également été ajouté à JavaScript. Iterator nous permet d'éviter d'avoir à initialiser les variables de collection et d'index. Au lieu de cela, nous utilisons la méthode next de l'objet itérateur pour renvoyer la valeur de l'élément suivant de la collection, qui est orientée vers la programmation.
Les itérateurs sont des objets avec une interface spéciale. Contient une méthode next(). L'appel renvoie un objet contenant deux attributs, à savoir value et done. Value représente la valeur de la position actuelle, et done indique si l'itération est terminée. Lorsqu'il est vrai, l'appel de next n'est pas valide.
Le parcours des collections dans ES5 utilise généralement une boucle for. Les tableaux ont également une méthode forEach, et les objets sont for-in Map et Set ont été ajoutés dans ES6, et les itérateurs peuvent gérer toutes les données de collection de manière unifiée. L'itérateur est une interface Tant que votre structure de données expose une interface d'itérateur, l'itération peut être effectuée. ES6 a créé une nouvelle commande de parcours pour la boucle for...of, et l'interface Iterator est principalement utilisée pour la consommation par for...of.
2. Comment utiliser les itérateurs ?
1. Interface Iterator par défaut
Tant que l'interface Iterator est déployée dans la structure de données, nous appellerons cette structure de données "Itérable". ES6 stipule que l'interface Iterator par défaut est déployée dans la propriété Symbol.iterator de la structure de données. En d'autres termes, tant qu'une structure de données contient des données Symbol.iterator, elle peut être considérée comme « traversable » (itérable).
Structure de données native qui peut être consommée par...of
Array
Map
Set
String
TypedArray (un type de tampon générique de longueur fixe qui permet de lire à partir du tampon des données binaires )
L'objet arguments dans la fonction
Objet NodeList
est visible ci-dessus Là il n'y a pas d'objet (Object) dans la structure de données native. Pourquoi ?
C'est parce que l'ordre de parcours des propriétés de l'objet est incertain et doit être spécifié manuellement par le développeur. Essentiellement, le traverseur est un processus linéaire. Pour toute structure de données non linéaire, déployer l'interface du traverseur équivaut à déployer une transformation linéaire.
Effectuez le traitement suivant pour rendre l'objet disponible à la consommation par pour...de :
// code1 function Obj(value) { this.value = value; this.next = null; } Obj.prototype[Symbol.iterator] = function() { var iterator = { next: next }; var current = this; function next() { if (current) { var value = current.value; current = current.next; return { done: false, value: value }; } else { return { done: true }; } } return iterator; } var one = new Obj(1); var two = new Obj(2); var three = new Obj(3); one.next = two; two.next = three; for (var i of one) { console.log(i); } // 1 // 2 // 3
2 Lorsque l'interface Iterator est appelée
. (1) Affectation de déconstruction
// code2 let set = new Set().add('a').add('b').add('c'); let [x,y] = set; // x='a'; y='b' let [first, ...rest] = set; // first='a'; rest=['b','c'];
(2) Opérateur Spread
// code3 // 例一 var str = 'hello'; [...str] // ['h','e','l','l','o'] // 例二 let arr = ['b', 'c']; ['a', ...arr, 'd'] // ['a', 'b', 'c', 'd']
(3) Expression de rendement* dans la fonction Générateur (introduite dans le chapitre suivant)
// code4 let generator = function* () { yield 1; yield* [2,3,4]; yield 5; }; var iterator = generator(); iterator.next() // { value: 1, done: false } iterator.next() // { value: 2, done: false } iterator.next() // { value: 3, done: false } iterator.next() // { value: 4, done: false } iterator.next() // { value: 5, done: false } iterator.next() // { value: undefined, done: true }
(4) Autres occasions
pour..de
Array.from
Map(), Set(), WeakMap(), WeakSet()
Promise.all()
Promise.race( )
3. Avantages de la boucle for...of
Regardons d'abord les inconvénients de la méthode array forEach :
// code5 myArray.forEach(function (value) { console.log(value); });
Le problème avec cette façon d'écrire est que , ne peut pas sortir de la boucle forEach à mi-chemin, et ni la commande break ni la commande return ne prennent effet.
Regardez encore, les défauts de l'objet for...en boucle :
for (var index in myArray) { console.log(myArray[index]); };
Le nom de clé du tableau est un nombre, mais le for. ..in loop Les chaînes sont utilisées comme noms de clé, "0", "1", "2", etc. La boucle
for...in peut non seulement parcourir les noms de clés numériques, mais également parcourir les recommandations de périodes ajoutées manuellement, même les clés de la chaîne prototype.
Dans certains cas, la session en boucle for...in parcourt les noms de clés dans n'importe quel ordre
la traversée for...in est principalement for Conçu pour parcourir des objets, il ne convient pas pour parcourir des tableaux
Alors, quels sont les avantages significatifs de for...of ?
a la même syntaxe concise que for...in, mais n'a pas les défauts de for...in
Différent de la méthode forEach, elle peut être utilisée avec break, continue et return
Fournit une interface d'opération unifiée pour parcourir toutes les structures de données
for (var n of fibonacci) { if (n > 1000) { break; console.log(n); } }
4. Comment utiliser la boucle for...of pour les types de données ?
(1) Array
for...of boucle permet de parcourir le tableau pour obtenir des valeurs clés
var arr = ['a', 'b', 'c', 'd']; for (let a in arr) { console.log(a); // 0 1 2 3 } for (let a of arr) { console.log(a); // a b c d }
for...of boucle appelle l'interface traverser , l'interface array traverseur ne renvoie que des valeurs avec des index numériques
let arr = [3, 5, 7]; arr.foo = 'hello'; for (let i in arr) { console.log(i); // "0", "1", "2", "foo" } for (let i of arr) { console.log(i); // "3", "5", "7" }
(2) Structures Map et Set
var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]); for (var e of engines) { console.log(e); } // Gecko // Trident // Webkit var es6 = new Map(); es6.set("edition", 6); es6.set("committee", "TC39"); es6.set("standard", "ECMA-262"); for (var [name, value] of es6) { console.log(name + ": " + value); } // edition: 6 // committee: TC39 // standard: ECMA-262
Comme on peut le voir sur le code ci-dessus, for ...of parcourt les structures Map et Set dans l'ordre dans lequel chaque membre est ajouté à la structure de données Lorsque la structure Set est parcourue, une valeur est renvoyée, tandis que lorsque la structure Map est parcourue, un tableau est renvoyé. Les deux membres sont le nom de clé et la valeur de clé du membre Map actuel.
(3) Objet de type tableau
String
// 普通的字符串遍历 let str = "yuan"; for (let s of str) { console.log(s); // y u a n } // 遍历含有 32位 utf-16字符的字符串 for (let x of 'a\uD83D\uDC0A') { console.log(x); } // 'a' // '\uD83D\uDC0A'
Objet DOM NodeList
let paras = document.querySelectorAll("p"); for (let p of paras) { p.classList.add("test"); }
objet arguments
function printArgs() { for (let x of arguments) { console.log(x); } } printArgs("a", "n"); // "a" // "n"
Traitement traversant des objets de tableau sans classe d'interface Iterator
Méthode Borrow Array.from pour le traitement
let arrayLike = { length: 2, 0 : 'a', 1 : 'b' }; // 报错 for (let x of arrayLike) { console.log(x); } // 正确 for (let x of Array.from(arrayLike)) { console.log(x); }
(4 ) Objet
Pour les objets ordinaires, vous ne pouvez pas utiliser directement for...of pour parcourir, sinon une erreur sera signalée et l'interface Iterator doit être déployée avant de pouvoir être utilisée. Déployez selon les deux méthodes suivantes :
// 方法一:使用 Object.keys 方法讲对象的键名生成一个数组 for (var key of Object.keys(someObject)) { console.log(key + ": " + someObject[key]); } // 方法二:使用Generator 函数将对象重新包装一下 function * entries(obj) { for (let key of Object.keys(obj)) { yield[key, obj[key]]; } } for (let[key, value] of entries(obj)) { console.log(key, "->", value); } // a -> 1 // b -> 2 // c -> 3
3. Exemples d'applications Iterator
.1、斐波那契数列
下面我们就使用迭代器来自定义自己的一个斐波那契数列组,我们直到斐波那契数列有两个运行前提,第一个前提是初始化的前两个数字为0,1,第二个前提是将来的每一个值都是前两个值的和。这样我们的目标就是每次都迭代输出一个新的值。
var it = { [Symbol.iterator]() { return this }, n1: 0, n2: 1, next() { let temp1 = this.n1, temp2 = this.n2; [this.n1, this.n2] = [temp2, temp1 + temp2] return { value: temp1, done: false } } } for (var i = 0; i < 20; i++) { console.log(it.next()) } // "value": 0, "done": false } { "value": 1, "done": false } { "value": 1, "done": false } { "value": 2, "done": false } { "value": 3, "done": false } { "value": 5, "done": false }... { "value": 2584, "done": false } { "value": 4181, "done": false }
2、任务队列迭代器
我们可以定义一个任务队列,该队列初始化时为空,我们将待处理的任务传递后,传入数据进行处理。这样第一次传递的数据只会被任务1处理,第二次传递的只会被任务2处理… 代码如下:
var Task = { actions: [], [Symbol.iterator]() { var steps = this.actions.slice(); return { [Symbol.iterator]() { return this; }, next(...args) { if (steps.length > 0) { let res = steps.shift()(...args); return { value: res, done: false } } else { return { done: true } } } } } } Task.actions.push(function task1(...args) { console.log("任务一:相乘") return args.reduce(function(x, y) { return x * y }) }, function task2(...args) { console.log("任务二:相加") return args.reduce(function(x, y) { return x + y }) * 2 }, function task3(...args) { console.log("任务三:相减") return args.reduce(function(x, y) { return x - y }) }); var it = Task[Symbol.iterator](); console.log(it.next(10, 100, 2)); console.log(it.next(20, 50, 100)) console.log(it.next(10, 2, 1)) // 任务一:相乘 { "value": 2000, "done": false }任务二:相加 { "value": 340, "done": false }任务三:相减 { "value": 7, "done": false }
3、延迟执行
假设我们有一个数据表,我们想按大小顺序依次的获取数据,但是我们又不想提前给他排序,有可能我们根本就不去使用它,所以我们可以在第一次使用的时候再排序,做到延迟执行代码:
var table = { "d": 1, "b": 4, "c": 12, "a": 12 } table[Symbol.iterator] = function() { var _this = this; var keys = null; var index = 0; return { next: function() { if (keys === null) { keys = Object.keys(_this).sort(); } return { value: keys[index], done: index++>keys.length }; } } } for (var a of table) { console.log(a) } // a b c d
四、结语
本章内容,重点是明白 Iterator 接口的机制,以及 for...of 循环的使用方法。
相关推荐:
关于PHP聚合式迭代器接口IteratorAggregate用法分享
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!