Cet article vous présente la méthode d'interface unifiée pour accéder à la collecte de données par Iterator. Elle a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
TraverserIterator
est une interface unifiée fournie par ES6 pour accéder aux collections de données. Pour toute collecte de données disposant d'une interface Traverser déployée en interne, les utilisateurs peuvent obtenir la structure de données correspondante de la même manière. Si vous utilisez la dernière version du navigateur Chrome
, alors vous devez savoir que la Miss Argument que nous connaissons a tranquillement ouvert un autre chemin vers son cœur.
Une certaine collection de données déploie l'interface Iterator
, ce qui signifie que son attribut Symbol.iterator
pointe vers une fonction qui renvoie l'interface Iterator
. Toute méthode qui utilise un traverseur par défaut pour accéder à une collection de données appellera cette propriété pour obtenir l'objet traverseur, puis accédera aux membres de la structure de données dans l'ordre défini (voir la lecture étendue dans la dernière section pour Symbol.iterator
) . Par exemple, le traverseur d'un tableau natif est [][Symbol.iterator]
, et Array.prototype[Symbol.iterator]
peut également être obtenu directement via le prototype de son constructeur.
L'appel de l'interface Iterator
renverra un nouvel objet traverseur (objet pointeur). Il doit y avoir une méthode
dans l'objet next
, qui est utilisée pour accéder au membre de données suivant. Le pointeur pointe initialement vers le début de la structure de données actuelle.
La première fois que la méthode next
de l'objet est appelée, le pointeur pointe vers le premier membre de la structure de données.
La deuxième fois que la méthode next
de l'objet est appelée, le pointeur pointe vers le deuxième membre de la structure de données.
Appelle en continu la méthode next
de l'objet jusqu'à ce qu'elle pointe vers la fin de la structure de données.
Chaque fois que la méthode next
est appelée, la même structure de données sera renvoyée : { value, done }
.
où value
représente la valeur pointant actuellement vers le membre, sinon, c'est undefined
.
où done
est une valeur booléenne, indiquant si le parcours se termine, la fin est true
, sinon false
.
Le standard de l'interface traverser est très simple et ne fournit pas de méthodes telles que faire fonctionner des pointeurs internes, déterminer s'il y a une valeur, etc. Continuez simplement à appeler la méthode next
, obtenez le done
actuel lorsque false
est value
et arrêtez-vous lorsque done
est true
. La première fois que je suis entré en contact avec le comportement du traverseur, c'était à l'hiver 2016. À cette époque, je n'avais pas suffisamment d'expérience pour comprendre l'applicabilité et le pouvoir de la simplicité. Ce n'est que maintenant, juste avant d'être sur le point de faire mes valises et d'être obligé de quitter l'entreprise, que je me suis soudainement réveillé. Quelle douloureuse prise de conscience.
let iterator = [1, 2, 3][Symbol.iterator](); console.log( iterator.next() ); // {value: 1, done: false} console.log( iterator.next() ); // {value: 2, done: false} console.log( iterator.next() ); // {value: 3, done: false} console.log( iterator.next() ); // {value: undefined, done: true}
Pour différentes structures de données, il existe différentes méthodes d'implémentation du traverseur. Nous implémentons simplement la méthode du traverseur de tableau.
let res = null; let iterator = myIterator([3, 7]); console.log( iterator.next() ); // {value: 3, done: false} console.log( iterator.next() ); // {value: 7, done: false} console.log( iterator.next() ); // {value: undefined, done: true} function myIterator(array = []) { let index = 0; return { next() { return index < array.length ? { value: array[index++], done: false } : { value: undefined, done: true }; } }; }
En plus de déployer la méthode next
pour l'objet traverseur, il peut également y avoir des méthodes return
et throw
. La méthode return
sera appelée lors de la sortie anticipée de la boucle for of
(généralement à cause d'une erreur ou du déclenchement de l'instruction break
). La méthode throw
est principalement utilisée en conjonction avec la fonction Generator
Les objets traverseurs généraux n'utilisent pas cette méthode, elle ne sera donc pas présentée.
let obj = { [Symbol.iterator]() { let index = 0; let array = [1, 2, 3]; return { next() { return index < array.length ? { value: array[index++], done: false } : { value: undefined, done: true }; }, return() { console.log('Trigger return.'); return {}; } }; } }; for (let v of obj) { console.log(v); // 打印出:1, 2, 3,没触发 return 函数。 } for (let v of obj) { if (v === 2) break; console.log(v); // 打印出:1,之后触发 return 函数。 } for (let v of obj) { if (v === 3) break; console.log(v); // 打印出:1, 2,之后触发 return 函数。 } for (let v of obj) { if (v === 4) break; console.log(v); // 打印出:1, 2, 3,没触发 return 函数。 } for (let v of obj) { if (v === 2) throw Error('error'); console.log(v); // 打印出:1,之后触发 return 函数,并报错停止执行。 }
Les structures de données de l'interface de traverseur de maintien par défaut natif sont :
Type de base : Array
, Set
, Map
(quatre ensembles de données de base : Array
, Object
, Set
et Map
).
Objets de type tableau : arguments
, NodeList
, String
.
let iterator = '123'[Symbol.iterator](); console.log( iterator.next() ); // {value: "1", done: false} console.log( iterator.next() ); // {value: "2", done: false} console.log( iterator.next() ); // {value: "3", done: false} console.log( iterator.next() ); // {value: undefined, done: true}
Traverseurs et méthodes de traversée précédentes
Ce n'est pas parce qu'une collection de données a une interface de traversée que toutes les méthodes qui la traversent utilisent cette interface. En fait, seules quelques nouvelles méthodes et certaines méthodes ajoutées dans ES6 seront utilisées, qui seront présentées ci-dessous. Pour les tableaux, l'utilisation de for
et for of
peut accéder aux mêmes membres, mais les opérations réelles sont différentes.
// 改变数组默认的遍历器接口。 Array.prototype[Symbol.iterator] = function () { let index = 0; let array = this; console.log('Use iterator'); return { next() { return index < array.length ? { value: array[index++], done: false } : { value: undefined, done: true }; } } }; let arr = [1, 2]; for (let v of arr) { console.log(v); // 打印出 Use iterator, 1, 2。 } for (let i = 0; i < arr.length; i++) { console.log(arr[i]); // 打印出 1, 2。 } arr.forEach(d => { console.log(d); // 打印出 1, 2。 });
L'objet n'a pas d'interface traverseur par défaut
Pourquoi l'objet n'a-t-il pas d'interface traverseur par défaut ? Cela doit être expliqué sous deux aspects. Premièrement, le traverseur est une structure de traitement linéaire.Pour toute structure de données non linéaire, déployer l'interface traverseur équivaut à déployer une transformation linéaire. Deuxièmement, l'objet est à l'origine une collection non ordonnée. Si vous souhaitez qu'il soit ordonné, vous pouvez utiliser Map
à la place. Cela signifie que chacun a ses propres atouts et chacun a ses propres devoirs. Si le bousier ne roule pas la boule de fumier et ne va pas chercher du miel, alors, eh bien, la bouquetière pourrait en souffrir.
自行生成的类数组对象(拥有length
属性),不具备遍历器接口。这与String
等原生类数组对象不同,毕竟人家是亲生的,一出生就含着金钥匙(也不怕误吞)。不过我们可以将数组的遍历器接口直接应用于自行生成的类数组对象,简单有效无副作用。
let obj = { 0: 'a', 1: 'b', length: 2, [Symbol.iterator]: Array.prototype[Symbol.iterator] }; let iterator = obj[Symbol.iterator](); console.log( iterator.next() ); // {value: "a", done: false} console.log( iterator.next() ); // {value: "b", done: false} console.log( iterator.next() ); // {value: undefined, done: true}
为对象添加遍历器接口,也不影响之前不使用遍历器的方法,比如for in
, Object.keys
等等(两者不等同)。
let obj = { 0: 'a', 1: 'b', length: 2, [Symbol.iterator]: Array.prototype[Symbol.iterator] }; console.log( Object.keys(obj) ); // ["0", "1", "length"] for (let v of obj) { console.log(v); // 依次打印出:"a", "b"。 } for (let k in obj) { console.log(k); // 依次打印出:"0", "1", "length"。 }
for of for of
是专门用来消费遍历器的,其遍历的是键值(for in
遍历的是键名)。
for (let v of [1, 2, 3]) { console.log(v); // 依次打印出:1, 2, 3。 }
扩展运算符
无论是解构赋值或扩展运算都是默认调用遍历器的。
let [...a] = [3, 2, 1]; // [3, 2, 1] let b = [...[3, 2, 1]]; // [3, 2, 1]
yield*
在Generator
函数中有yield*
命令,如果其后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。
for (let v of G()) { console.log(v); // 依次打印出:1, 2, 3, 4, 5 } function* G() { yield 1; yield* [2,3,4]; yield 5; }
其它场合
有些接受数组作为参数的函数,会默认使用数组的遍历器接口,所以也等同于默认调用。比如Array.from()
, Promise.all()
。
相关推荐:
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!