迭代器由任意对象实现的接口,支持连续获取对象产出的每个值; 默认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 };}}}}}
考察点:
- 给出打印结果并说明原因
let arr = [1,2,3]arr.name = 'Jack'arr.length // 3console.log(Object.keys(arr)) // ["0", "1", "2", "name"]for(let i in arr) { console.log('in', i) } // 0, 1, 2, 3, namefor (let i of arr) { console.log(i) } // 1, 2, 3
- for…in 是枚举全部属性
- for…of 是迭代器
- 改造数据使得for…of可遍历出全部值
解决方法1:
let arr = [1,2,3]arr.name = 'Jack'// Symbol.iteratorarr[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.iteratorarr[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
疑问:
- for (let item of arr ) {iter.next()} 与 for(let item of iter) 区别?
- 提前终止, 出发迭代器是否重新开始
