迭代器
迭代器
可迭代对象和迭代器是ES6的一个特性,迭代器可使用 for/of 进行迭代
for(let i of [1, 2, 3]){ console.log(i); }
迭代器可使用扩展操作符,也可进行解构
let chars = [..."abcde"] // ["a", "b", "c", "d", "e"] let o = {a:1, b:2, c:3, d:4} let {a, b, c, d} = o
可迭代对象的迭代器方法使用了符号 Symbol.iterator 作为名字,重复调用使用next()方法,next()方法会返回一个迭代结果对象,该结果对象有两个属性,value,done,value代表值,done代表是否停止,当done为true时,就意味着到了末尾,下列代码等同于 for/of
let iterable = [99, 100] let iterator = iterable[Symbol.iterator]() for(let result = iterator.next(); !result.done; result = iterator.next()){ console.log(result.value) }
自定义一个可迭代的类
创建一个可迭代的集合类
class Range{ constructor(from, to){ this.from = from this.to = to } has(x){ return typeof x === "number" && this.from <= x <= this.to} toString() { return `{x| ${this.from} <= x <= ${this.to} }`} [Symbol.iterator](){ let next = Math.ceil(this.from) // 向上取整,小数部分舍去,整数部分加1 let last = this.to return { next(){ return next <= last? {value:next++, done:false}: {done:true} }, [Symbol.iterator](){return this} } } } for(let i of new Range(0, 10)){ console.log(i) }
迭代器的惰性
迭代器又叫惰性器,可以让需求一步一步进行,比如字符串的split()方法,哪怕一个单词都没有使用,也要全部处理完保存在数组中,此时就可用迭代器一步一步进行处理
function words(s){ let r = /\s+|$/g // 匹配一个或多个空格或末尾 r.lastIndex = s.match(/[^ ]/).index // 开始匹配第一个非空格 return { // 返回一个可迭代的迭代器对象 [Symbol.iterator](){ return this }, next(){ let start = r.lastIndex // 从上次匹配结束的地方恢复 if(start < s.length){ // 如果好美处理完 let match = r.exec(s) // 匹配下一个单词的边界 if(match){ // 如果找到了一个单词,返回 return { value: s.substring(start, match.index)} } } return { done: true } // 否则返回表示处理完成的结果 } } } [...words("abc def ghi")] // [ 'abc', 'def', 'ghi' ]
关闭迭代器
如果再上述迭代器中,我们不是接收字符,而是接收文件名,打开文件迭代行,常规的操作都会在最后关闭文件,但可能由于break,return或异常终止提前结束导致文件不能正常关闭或释放内存,为此,除了next()方法,迭代器还能实现return()方法,如果迭代器在next()返回done属性为true的迭代结果之前停止,解释器就会检查是否存在return()方法,如果有,就会调用,让迭代器有机会做一些清理工作