ES6迭代器遍历元素
遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
下面以对象为例,一步一步推导一下为数据结构添加接口的方法,最后再总结一下。
首先创建一个对象
let six = {
name: "six",
member: ['zhuxiaoming', 'wangzha', 'qiuqiu', 'mixian', 'mogutou', 'runtu']
}
需求:使用面向对象的编程思想,遍历打印对象six里的member属性这个数组。
我们可以给这个对象添加一个迭代器,并遍历打印。
let six = {
name: "six",
member: ['zhuxiaoming', 'wangzha', 'qiuqiu', 'mixian', 'mogutou', 'runtu'],
// 添加一个迭代器
[Symbol.iterator](){}
}
//遍历打印
for (let v of six){
console.log(v);
}
此时执行上面代码报错Result of the Symbol.iterator method is not an object
,说明Symbol.iterator这个方法的返回值是一个对象,所以我们加一个对象作为返回值。
// 首先创建一个对象
let six = {
name: "six",
member: ['zhuxiaoming', 'wangzha', 'qiuqiu', 'mixian', 'mogutou', 'runtu'],
// 添加一个迭代器
[Symbol.iterator]() {
// 添加一个返回值(对象)
return {};
}
}
// 遍历打印
for (let v of six) {
console.log(v);
}
再次执行,报错undefined is not a function
,这里时因为缺少了方法next
,(指针对象的next方法,用来移动指针。开始时,指针指向数组的开始位置。然后,每次调用next方法,指针就会指向数组的下一个成员。next方法返回一个对象,表示当前数据成员的信息。这个对象具有value和done两个属性,value属性返回当前位置的成员,done属性是一个布尔值,表示遍历是否结束,即是否还有必要再一次调用next方法。)
所以,我们再给返回的对象里添加一个next
方法,该方法返回一个包含value和done两个属性的对象。
// 首先创建一个对象
let six = {
name: "six",
member: ['zhuxiaoming', 'wangzha', 'qiuqiu', 'mixian', 'mogutou', 'runtu'],
// 添加一个迭代器
[Symbol.iterator]() {
// 添加一个返回值(对象)
return {
// 添加next方法
next: function () {
// 返回一个对象
return { value: 'value值随便写的', done: false };
}
};
}
}
// 遍历打印
for (let v of six) {
console.log(v);
}
这里准备好再执行,你会发现控制台开始疯狂打印value值随便写的
,赶紧关掉页面。
这里是因为我们done属性设置为false,即标识未遍历完,所以会一直打印,而value就是打印的内容。
因此我们需要创建一个索引,一方面可以作一个判断再决定done返回true还是false,另一方面给value赋值。
注意index的声明位置。
// 首先创建一个对象
let six = {
name: "six",
member: ['zhuxiaoming', 'wangzha', 'qiuqiu', 'mixian', 'mogutou', 'runtu'],
// 添加一个迭代器
[Symbol.iterator]() {
// 保存this
let _this = this;
// 添加索引
let index = 0;
// 添加一个返回值(对象)
return {
// 添加next方法
next: function () {
// 每次调用next方法判断一下是否遍历完
if (index < _this.member.length) {
// 保存一下返回结果,因为索引要更新
const result = { value: _this.member[index], done: false };
// 索引自加
index++;
// 返回一个对象
return result;
} else {
// 遍历完成,返回
return { value: undefined, done: true };
}
}
};
}
}
// 遍历打印
for (let v of six) {
console.log(v);
}
这样就可以使用for...of
遍历打印对象里属性的值数组啦
补充一下Iterator的遍历过程
Iterator 的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是 ES6 创造了一种新的遍历命令for…of循环,Iterator 接口主要供for…of消费。
Iterator 的遍历过程是这样的。
(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
(2)第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
(3)第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
(4)不断调用指针对象的next方法,直到它指向数据结构的结束位置。
每一次调用next方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含value和done两个属性的对象。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。
————阮一峰《ECMAScript 6 入门》