迭代器

迭代器

可迭代对象和迭代器是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()方法,如果有,就会调用,让迭代器有机会做一些清理工作
posted @ 2021-12-18 19:54  邢韬  阅读(52)  评论(0编辑  收藏  举报