ES5中遍历集合通常都是 for循环,数组还有 forEach 方法,对象就是 for-in,ES6 中又添加了 Map 和 Set,而迭代器可以统一处理所有集合数据的方法。迭代器是一个接口,只要你这个数据结构暴露了一个iterator的接口,那就可以完成迭代。ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。
迭代器是带有特殊接口的对象。含有一个next()方法,调用返回一个包含两个属性的对象,分别是value和done,value表示当前位置的值,done表示是否迭代完,当为true的时候,调用next就无效了。
一个数据结构只要具有 Symbol.iterator 数据,就可以认为是“可遍历的”(iterable)。
const items = ["zero", "one", "two"]; const it = items[Symbol.iterator](); it.next(); // >{value: "zero", done: false} it.next(); // >{value: "one", done: false} it.next(); // >{value: "two", done: false} it.next(); // >{value: undefined, done: true}
以下是可迭代的值:
注:普通对象不能迭代。做如下处理,可使对象可以迭代
// 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
调用 Iterator 接口的场合
(1) 解构赋值
// 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) 扩展运算符
// code3 // 例一 var str = ‘hello‘; [...str] // [‘h‘,‘e‘,‘l‘,‘l‘,‘o‘] // 例二 let arr = [‘b‘, ‘c‘]; [‘a‘, ...arr, ‘d‘] // [‘a‘, ‘b‘, ‘c‘, ‘d‘]
(3)Generator 函数中的 yield* 表达式
// 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)其它场合
数组 forEach 缺点:无法中途跳出 forEach 循环,break 命令或 return 命令都不能生效
myArray.forEach(function (value) { console.log(value); });
对象 for...in 的循环的缺点:
for (var index in myArray) console.log(myArray[index]); };
for...of 有哪些显著的优点呢?
1、数组
for...of 循环调用遍历器接口,数组的遍历器接口只返回具有数字索引的值
let arr = [3, 5, 7]; arr.foo = ‘hello‘; for (let i in arr) { console.log(i); // "0", "1", "2", "foo"
console.log(arr[i]); // "3", "5", "7", "hello" }
for (let i of arr) { console.log(i); // "3", "5", "7" }
2、Map 和 Set 结构
for...of 循环遍历Map 和 Set 结构时,遍历的顺序是按照各个成员被添加进数据结构的顺序,Set 结构遍历时返回的是一个值,而 Map 结构遍历时返回的是一个数组
3、类数组对象
// 普通的字符串遍历 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‘
let paras = document.querySelectorAll("p"); for (let p of paras) { p.classList.add("test"); }
function printArgs() { for (let x of arguments) { console.log(x); } } printArgs("a", "n"); // "a" // "n"
没有 Iterator 接口类数组对象的遍历处理
借用 Array.from 方法处理
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); }
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()) }
2、任务队列迭代器
3、延迟执行
原文:https://www.cnblogs.com/liangtao999/p/11710787.html