一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天
迭代器(Iterator)
迭代器是一种特殊的对象,所有迭代器对象都有一个next()方法,每次调用都返回一个结果对象,结果对象有两个属性:
- value: 下一个将要返回的值
- done:它是一个布尔值,当没有更多可返回的数据时返回true
迭代器中会保存一个内部指针,用来指向当前集合中值的位置,每调用一次 next(),都会返回下一个可用的值。
模拟迭代器:
function createIterator(items){
var i = 0
return {
next : function(){
var done = (i>=items.length)
var value = !done ? items[i++]:undefined
}
}
}
var iterator = createIterator([1,2,3])
console.log(iterator.next())//{vlaue:1, done:false}
console.log(iterator.next())//{vlaue:2, done:false}
console.log(iterator.next())//{vlaue:3, done:false}
// 之后所有调用都返回如下内容
console.log(iterator.next())//{vlaue:undefined, done:true}
生成器(Generator)
生成器是一种返回迭代器的函数,它支持一边读取数据,一边生成数据,如果数据比较大时,这种机制可以节省很多空间。通过function关键字后的星号(*)来表示,函数中会用到新的关键字yield,生成器函数next()的返回值是创建好的迭代器
语法:在函数关键词后加上星号,以下写法都可以
function * generator () {}
function* generator () {}
function *generator () {}
let generator = function * () {}
let generator = function* () {}
let generator = function *() {}
let o = {
*generator(items){}
}
let generator = *() => {} // SyntaxError
let generator = ()* => {} // SyntaxError
let generator = (*) => {} // SyntaxError
关键词yield
可以通过它来指定调用迭代器的next()方法时的返回值及返回顺序。每当执行完一条yield语句函数会自动停止执行
yield使用限制
- yield关键字只能在生成器内部使用,其他地方使用会报错。生成器内部的函数里使用也会报错
- 它与return一样,不能穿透函数边界
生成器特点:
- 随时可以暂停
- 可以在任意时候恢复
- 生成器不能使用箭头函数
可迭代对象
可迭代对象具有Symbol.iterator属性,是一种与迭代器密切相关的对象。
- ES6中所有集合对象(数组、Set集合、Map集合都是可迭代对象)
- 通过生成器创建的迭代器都是可迭代对象,因为生成器默认回味Symbol.iterator属性赋值
for-of循环
for-of循环用于可迭代对象,它每执行一次都会调用可迭代对象的next()方法,并将迭代器返回的结果对象的value储存在变量中。
当迭代数组或集合中的值时,可以用for-of循环代替for循环,因为for-of循环的控制条件更简单,不需追踪复杂的条件,很少出错。
注意:如果将for-of用于非可迭代对象、null或undefined会报错。
Symbol.iterator
可以通过Symbol.iterator访问对象默认的迭代器:
let values = [1,2,3]
let iterator = values[Symbol.iterator]()
console.log(iterator.next())//{value:1, done:false}
console.log(iterator.next())//{value:2, done:false}
console.log(iterator.next())//{value:3, done:false}
console.log(iterator.next())//{value:undefined, done:true}
因为具有Symbol.iterator属性的对象都有默认的迭代器,所以判断一个对象是否为可迭代对象,可以通过Symbol.itemrator属性
function isIterator(object){
return typeof object[Symbol.iterator] === 'function'
}
console.log(isIterator([1,2,3])) // true
console.log(isIterator('hello')) // true
console.log(isIterator(new Map())) // true
console.log(isIterator(new Set())) // true
console.log(isIterator(new WeakMap())) // false
console.log(isIterator(new WeakSet())) // false