欢迎光临

木子屋

标题: ES6学习笔记：Iterator接口和Generator函数

作者: dnawo

日期: 2022-04-12 09:23 PM

分类: 脚本语言

内容: 一、Iterator接口
Iterator接口为各种不同的数据结构提供统一的访问机制，任何数据结构只要部署了Iterator，就可以完成遍历操作，举个例子：
复制内容到剪贴板 程序代码function customIterator(arr) {
let nextIndex = 0;
return {
next: function() {
if(nextIndex < arr.length){
return {value: arr[nextIndex++], done: false};
}else{
return {value: undefined, done: true};
}
}
};
}
let it = customIterator(['a', 'b']);
it.next(); //{value: 'a', done: false }
it.next(); //{value: 'b', done: false }
it.next(); //{value: undefined, done: true }
customIterator是实现Iterator接口的遍历器生成函数，调用该函数会返回一个遍历器，其内部有一个指针和一个next方法，每一次调用next方法都会移动指针和返回数据结构当前成员的信息，返回值是一个对象，格式为：{value, done}，value是当前成员的值，done是一个布尔值，表示遍历是否结束。
对于Array、Map、Set、String、TypedArray、函数的arguments对象、NodeList对象这些数据结构，Javascript原生给它们部署了Iterator，调用这些数据结构的Symbol.iterator属性即可得到遍历器生成函数：
复制内容到剪贴板 程序代码let arr = ['a', 'b'];
let it = arr[Symbol.iterator]();
it.next(); //{value: 'a', done: false }
it.next(); //{value: 'b', done: false }
it.next(); //{value: undefined, done: true }
二、Generator函数
Generator函数也是一个遍历器生成函数，它的实现方式和Iterator接口完全不同。Generator函数有两个特征，一是function关键字与函数名之间有一个星号，二是函数体内部使用yield表达式，定义不同的内部状态，每一次调用next方法运行到下一个yield并暂停，返回值和Iterator一样，value为yield表达式的值：
复制内容到剪贴板 程序代码function* customGenerator() {
yield 'a';
yield 'b';
}
let gt = customGenerator();
gt.next(); //{value: 'a', done: false }
gt.next(); //{value: 'b', done: false }
gt.next(); //{value: undefined, done: true }
换言之，Generator函数是分段执行的，yield表达式是暂停执行的标记，而next方法可以恢复执行。Generator函数调用时不会立即执行，直到调用next方法才开始执行。利用Generator函数这个特性，我们可以写出任意对象遍历器：
复制内容到剪贴板 程序代码function* customGenerator(obj) {
let propKeys = Reflect.ownKeys(obj);
for (let propKey of propKeys) {
yield [propKey, obj[propKey]];
}
}
let gt = customGenerator({name: 'Jack', age: 30});
gt.next(); //{value: ['name', 'Jack'], done: false }
gt.next(); //{value: ['age', 30], done: false }
gt.next(); //{value: undefined, done: true }
Generator函数也是一个遍历器生成函数，所以将它加到对象的Symbol.iterator属性上面也是可以的：
复制内容到剪贴板 程序代码let person = {
name: 'Jack',
age: 30,
[Symbol.iterator]: function* () {
let propKeys = Object.keys(this);
for (let propKey of propKeys) {
yield [propKey, this[propKey]];
}
}
};
let gt = person[Symbol.iterator]();
gt.next(); //{value: ['name', 'Jack'], done: false }
gt.next(); //{value: ['age', 30], done: false }
gt.next(); //{value: undefined, done: true }
三、for...of循环
一个数据结构只要部署了Symbol.iterator属性，就被视为具有iterator接口，就可以用for...of循环遍历它的成员：
复制内容到剪贴板 程序代码for(let item of arr){
console.log(item);
}
//a
//b
复制内容到剪贴板 程序代码for(let item of person){
console.log(item);
}
//['name', 'Jack']
//['age', 30]

+ 查看当前日志评论 (0)

登录

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 0.799 ms

返回

标题: ES6学习笔记：Iterator接口和Generator函数

你没有权限发表评论

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 0.799 ms

返回

暂无评论

返回

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 0.830 ms

返回