Skip to content

Latest commit

 

History

History
148 lines (116 loc) · 2.94 KB

2019-10-20-ES6迭代器.md

File metadata and controls

148 lines (116 loc) · 2.94 KB
slug title author author_url tags
ES6迭代器
ES6迭代器
Zhao chen

迭代器由任意对象实现的接口,支持连续获取对象产出的每个值; 默认Symbol.iterator 属性。

消费方式

  • 手动调用next()方法消费
  • for...of 循环自动消费(for( ; ; )、forEach)

迭代器模式, 可以支持迭代消费的数据结构(可迭代对象)

'12345'
[1, 2, 3, 4, 5]
new Map().set('a', 1).set('b', 2)
new Set().add(1).add(2).add(3)
arguments对象
NodeList等DOM集合类型

原生语言:for...of、数组结构、扩展操作符、Array.from()、创建集合、创建映射、Promise.all()、Promise.race()、yield*

let iter = [1, 2, 3, 4][Symbol.iterator]();
iter.next() // {done: false, value: 1}, 最后{value: undefined, done: true}

自定义迭代器

class Counter {
    constructor(limit) {
        this.limit = limit
    }

    [Symbol.iterator]() {
        let count = 1, limit = this.limit;
        return {
            next () {
                if (count <= limit) {
                    return { done: false, value: count++ };
                } else {
                    return { done: true, value: undefined };
                }
            } 
        } 
    }
}

考察点

  1. 给出打印结果并说明原因
let arr = [1,2,3]
arr.name = 'Jack'
arr.length // 3
console.log(Object.keys(arr)) // ["0", "1", "2", "name"]
for(let i in arr) { console.log('in', i) } // 0, 1, 2, 3, name
for (let i of arr) { console.log(i) } // 1, 2, 3
  • for...in 是枚举全部属性
  • for...of 是迭代器
  1. 改造数据使得for...of可遍历出全部值

解决方法1:

let arr = [1,2,3]
arr.name = 'Jack'

// Symbol.iterator

arr[Symbol.iterator] = function () {
    let index = 0;
    const _this = this;
    const keys = Object.keys(_this);
    const len = keys.length;
    return {
        next() {
            if (index < len) {
                return {
                    value: _this[keys[index++]],
                    done: false
                }
            }
            return {
                value: null,
                done: true
            }
        }
    }
}

let iter = arr[Symbol.iterator]()

for (let i of arr) {
    console.log(i)
}

// 1
// 2
// 3
// Jack

方式2: 生成器函数

let arr = [1,2,3]
arr.name = 'Jack'

// Symbol.iterator

arr[Symbol.iterator] = function* () {
    const keys = Object.keys(this);
    for (let i = 0; i < keys.length; i++) {
        yield this[keys[i]]
    }
}

let iter = arr[Symbol.iterator]()

for (let i of arr) {
    console.log(i)
}

// 1
// 2
// 3
// Jack

https://gitee.com/daaasheng/my_code_block/commit/b589b41274619c291a7b711ddada1fb72bd65a0e

疑问

  1. for (let item of arr) {iter.next()} 与 for(let item of iter) 区别?
  2. 提前终止, 出发迭代器是否重新开始