ES6迭代器遍历元素

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方法返回一个对象,表示当前数据成员的信息。这个对象具有valuedone两个属性,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 入门》

上一篇:不仅硬核游戏会坑人,来看看LeetCode出题人是怎么埋坑的


下一篇:【算法题】获取单向链表中倒数第 N 个节点