Iterator 和 for...of 循环

Iterator(遍历器)的概念

Iterator(遍历器)概念: 它是一种接口,为各种不同的数据结构提供统一的访问机制,即for...of循环,该循环会自动去寻找 Iterator 接口。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。

Iterator 的作用:

-提供一个统一的、简便的访问接口;
-使得数据结构的成员能够按某种次序排列;
-ES6 创造了一种新的遍历命令for...of循环,Iterator 接口主要供for...of消费。

原生具备Iterator接口的数据(可用for...of遍历的)

1、Array

2、arguments

3、Set

4、Map

5、String

6、typeArray

7、NoeList

ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性。(换句话说,所谓Iterator接口,其实在相当于是一个对象的属性。这个属性的名字叫Symbol.iterator

Symbol.iterator属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个遍历器。

来看一个简单例子

// 声明一个数组
var fruits = ['苹果', '香蕉', '西红柿', '榴莲'];
for (let k of fruits) {
    console.log(k);
}
// 苹果
// 香蕉
// 西红柿
// 榴莲

console.log(fruits); // 打印这个数组,数组中就有这个接口(Symbol.Iterator属性):Symbol(Symbol.iterator): ƒ values()

Iterator工作原理:

-创建一个指针对象,指向当前数据结构的起始位置;
-第一次调用对象的next方法,指针自动指向数据结构的第一个成员;
-接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员;
-每调用next方法返回一个包含value和done属性的对象

注:需要自定义遍历数据的时候,要想到遍历器

下面的例子是数组的Symbol.iterator属性。

// 声明一个数组
const fruits = ['苹果', '香蕉', '西红柿', '榴莲'];

// 获取数组的iterator对象
let iterator = fruits[Symbol.iterator]();

// 调用对象的next方法
console.log(iterator.next()); // {value: "苹果", done: false}
console.log(iterator.next()); // {value: "香蕉", done: false}
console.log(iterator.next()); // {value: "西红柿", done: false}
console.log(iterator.next()); // {value: "榴莲", done: false}
console.log(iterator.next()); // {value: undefined, done: true}

对象(Object)没有默认部署 Iterator 接口

const obj = {
    name: "终极一班",
    stu: ['唐僧', '孙悟空', '猪八戒', '沙和尚']
}

// 采用for...of遍历这个对象
for (var k of obj) {
    console.log(k);
}
// obj is not iterable

一个对象如果要具备可被for...of循环调用的 Iterator 接口,就必须在Symbol.iterator的属性上部署遍历器生成方法(原型链上的对象具有该方法也可)。

Iterator(遍历器)的应用

部署在对象身上 

 

let obj = {
    data: ['唐僧', '孙悟空', '猪八戒', '沙和尚'],
  // 部署iterator接口 [Symbol.iterator]() { let index
= 0; return { next: () => { if (index < this.data.length) { return { value: this.data[index++], done: false }; } return { value: undefined, done: true }; } }; } }; // 采用for...of遍历这个对象 for (let k of obj) { console.log(k); } // 唐僧 // 孙悟空 // 猪八戒 // 沙和尚

 

部署在原型上 

class RangeIterator {
    constructor(start, stop) {
        this.value = start;
        this.stop = stop;
    }
    // 部署遍历器接口
    [Symbol.iterator]() {
        return this;
    }

    next() {
        var value = this.value;
        if (value < this.stop) {
            this.value++;
            return {
                done: false,
                value: value
            };
        }
        return {
            done: true,
            value: undefined
        };
    }
}

var result = new RangeIterator(0, 3);

for (var value of result) {
    console.log(value); // 0, 1, 2
}

for...of 循环

一个数据结构只要部署了Symbol.iterator属性,就被视为具有 iterator 接口,就可以用for...of循环遍历它的成员。也就是说,for...of循环内部调用的是数据结构的Symbol.iterator方法。

for...of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象(比如arguments对象、DOM NodeList 对象)、后文的 Generator 对象,以及字符串。 

 

 

 

 

posted @ 2021-07-29 16:27  半白半黑  阅读(106)  评论(0)    收藏  举报