1. 遍历器(Iterator)
1.1 基本概念
- Iterator是一种机制(接口),并不是es6提供的一种标准类,为各种不同的数据结构提供统一的访问机制,任何数据结构之遥部署Iterator接口,就可以完成遍历操作,依次处理该数据结构的所有成员
- 拥有next方法用于一次遍历数据结构的成员
- 每一次遍历返回结果返回的结果是一个对象 {done: false, value: xxx}
- done 记录是否遍历完成
- value 当前遍历结果
class Iterator {
constructor(arr) {
this.arr = arr;
this.index = 0;
}
next() {
let index = this.index;
let arr = this.arr;
if (index > arr.length -1) {
return {
done: true,
valur: undefined,
};
}
return {
done: false,
valur: arr[this.index++], // 先运算取值,后++
};
}
}
let arr = [10, 20, 30]
let itor = new Iterator(arr)
console.log(itor.next()) // {done: false, valur: 10}
console.log(itor.next()) // {done: false, valur: 20}
console.log(itor.next()) // {done: false, valur: 30}
console.log(itor.next()) // {done: true, valur: undefined}
1.2 内置Symbol.iterator属性
-
只要拥有Symbol.iterator属性的数据结构(值),被称为可遍历的,可以基于
for of循环处理- 数组,Array.prototype -> Symbol(Symbol.iterator)
- 部分类数组:arguments/NodeList(节点集合)/HTMLCollection...
- String
- Set
- Map
- generator object
-
对象默认不具备Symbol.iterator属性,属于不可被遍历的数据结构
-
重构arr的遍历器
- for of / 展开运算符 都走遍历器机制
let arr = [10, 20, 30];
arr[Symbol.iterator] = function() {
// 返回一个符合iterator规范的对象,具备next方法
let index = 0;
let self = this;
return {
next() {
console.log('OK')
if (index > self.length -1) {
return {
done: true,
value: undefined,
};
}
let result = {
done: false,
value: self[index++],
};
return result
}
};
};
for (let item of arr) {
console.log(item)
}
console.log(...arr)
- 对象本身不是符合iterator遍历规范的数据结构
let obj = {
0: 10,
1: 20,
2: 30,
length: 3
};
for(let item of obj) {
console.log(item)
}
// Uncaught TypeError: obj is not iterable
- 让类数组对象可以遍历
let obj = {
0: 10,
1: 20,
2: 30,
length: 3,
// [Symbol.iterator]:Array.prototype[Symbol.iterator]
[Symbol.iterator]: function() {
let index = 0;
let self = this;
return {
next() {
return index>self.length-1? {done: true, vaule: undefined} : {done: false, value: self[index++]}
}
}
}
};
for(let item of obj) {
console.log(item)
}
// 10 20 30
- 让纯对象可以遍历
- symbol唯一值,会遍历到自己写的iterator,无法排除,放到公有属性
2. 生成器对象(generator)
2.1 生成器函数基本用法
-
生产器对象是由一个generator function返回的,并且它符合可迭代协议和迭代器(Iterator)协议
-
加 *
生成器函数
function* func() {
}
func.prototype.AA = '10'
let iterator = func();
// 返回值是当前func的一个实例
// iterator.__proto__ === func.protorype
// console.log(iterator instanceof func) // true
// func 本身无法被new
console.log(iterator)
- 用法
function* func() {
console.log('A');
yield 1;
console.log('B');
yield 2;
console.log('C');
yield 3;
console.log('D');
}
let iterator = func();
console.log(iterator.next()); // 遇到一个yield就结束,再打印,从上一次yiled到下一个yield
2.2 next参数,给yield返回值赋值
function* func() {
let x = yield 1;
console.log(x); // -> 10
}
let iterator = func();
iterator.next() // {vaule: 1, done: false}
iterator.next() // x是undefined {vaule: undefined, done: true}
如果 iterator.next(10) , yield返回值为10,赋给x,x打印10
2.3 一个生成器中调用另一个生成器函数
function* func1() {
yield 1;
yield 2;
}
function* func2() {
yield 3;
yield* func1();
yield 4;
}
let iterator = func2();
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
3 调用的写法
- async+await就是generator+promise处理的语法糖
3.1 异步串行then调用写法
const func = x => {
return new Promise(resolve => {
setTimeout(() => {
reslove(++x); // ++x 先累加后操作
}, 1000)
})
}
// 异步串行写法,上一个返回值传给下一个
func(0).then(x => {
console.log(x); // 1
return func(x);
}).then(x => {
console.log(x); // 2
return func(x);
}).then(x => {
console.log(x); // 3
})
3.2 saync/await写法
(async function anonymous() {
let x = await func(0);
console.log(x)
x = await func(x)
console.log(x)
x = await func(x)
console.log(x)
})();
3.3 generator写法
function* generator(x) {
x = yield func(x);
console.log(x); // 1
x = yield func(x);
console.log(x); // 2
}
// 知道多少次,写死
let iterator = generator(0);
let result = iterator.next(); // 返回一个promise实例,{value: Promise, done: false}
result.value.then(x => {
result = iterator.next(x); // 第一次的结果作为值传递下去
result.value.then(x => {
result = iterator.next(x);
})
});
// generator生成器函数,params初始执行generator传递的参数
function async(generator, ...params) {
const iterator = generator(...params);
}