ES6 |迭代器Iterator

102 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

ES系列文章

Iterator迭代器

迭代器的作用就是统一的接口机制,来处理所有不同的数据结构。任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。

Iterator的作用有三个:

  1. 为各种数据结构,提供一个统一的、简便的访问接口。
  2. Iterator接口主要供for...of消费。
  3. 使得数据结构的成员能够按某种次序排列。
function makeIterator(arr) {
    let nextIndex = 0
    return {
        next() {
            return nextIndex < arr.length ? {
                value: arr[nextIndex++],
                done: false
            } : {
                value: undefined,
                done: true
            }
        }
    }
}
let it = makeIterator(['a', 'b', 'c'])
console.log(it.next())
console.log(it.next())
console.log(it.next())
console.log(it.next())

Iterator的遍历过程

  • 创建一个指针对象,指向当前数组的初始位置。遍历器对象本质上,就是一个指针对象。
  • 第一次调用指针对象的next方法,可以将指针指向数组的第一个成员。
  • 第二次调用指针对象的next方法,指针就指向数组的第二个成员。
  • 不断调用指针对象的next方法,直到它指向数组的结束位置。
let courses = {
    allCourse: {
        frontend: ['ES', '小程序', 'Vue', 'React'],
        backend: ['Java', 'Python', 'SpringBoot'],
        webapp: ['Android', 'IOS']
    }
}
for(let c of courses){
    console.log(c)
}
let arr = ['a', 'b', 'c']
console.log(arr)
let it = arr[Symbol.iterator]()
console.log(it.next())
console.log(it.next())
console.log(it.next())
console.log(it.next())

//可迭代协议:Symbol.iterator
//迭代器协议:return { next(){ return{value, done} }}
courses[Symbol.iterator] = function () {
    let allCourse = this.allCourse
    let keys = Reflect.ownKeys(allCourse)
    let values = []
    return {
        next() {
            if (!values.length) {
                if (keys.length) {
                    values = allCourse[keys[0]]
                    keys.shift()
                }
            }
            return {
                done: !values.length,
                value: values.shift()
            }
        }
    }
}

for (let c of courses) {
    console.log(c)
}

原生具备Iterator接口的数据结构

  • Array
  • Map
  • Set
  • String
  • TypedArray
  • 函数的arguments 对象
  • NodeList对象

arguments 对象

// generator
courses[Symbol.iterator] = function* () {
    let allCourse = this.allCourse
    let keys = Reflect.ownKeys(allCourse)
    let values = []
    while (1) {
        if (!values.length) {
            if (keys.length) {
                values = allCourse[keys[0]]
                keys.shift()
                yield values.shift()
            } else {
                return false
            }
        }else{
            yield values.shift()
        }
    }
}
for (let c of courses) {
    console.log(c)
}

一个前端小白,若文章有错误内容,欢迎大佬指点讨论!