JavaScript可迭代对象和迭代器

JavaScript可迭代对象

可迭代对象(Iterable)是实现了[Symbol.Iterator]方法的对象。[Symbol.Iterator]方法应该返回一个迭代器(Iterator)。

JavaScript迭代器

迭代器(Iterator)是实现了next方法的对象。next方法会返回{ value: T, done: bool }结构的对象。T表示任意类型的对象。
可以把可迭代对象和迭代器合并为一个对象,也就是说同时实现[Symbol.Iterator]方法和next方法。

迭代器遍历语法

// makeRangeIterable的实现见下面
let iterable = makeRangeIterable(1, 10, 2);
for (let v of iterable) {
   console.log(v);
}

上面的循环是个语法糖,等价于下面的语句:

for(let iterator = iterable[Symbol.iterator](), v = iterator.next();
  !v.done ;
  v = iterator.next()) {
    console.log(v.value);
}

手工方法实现可迭代对象

函数实现可迭代对象

function makeRangeIterable(start = 0, end = Infinity, step = 1) {
    const rangeIterable = {
        [Symbol.iterator]: function() {
            return {
                nextIndex: start,
                next: function() {
                    let result;
                    if (this.nextIndex < end) {
                        result = { value: this.nextIndex, done: false }
                        this.nextIndex += step;
                        return result;
                    }
                    return {  done: true }
                }
            }
       }
    };
    return rangeIterable;
}

类实现可迭代对象

class RangeIterator
{
    nextIndex = 0;
    end = Infinity;
    step = 1;
    constructor(start = 0, end = Infinity, step = 1)
    {
        this.nextIndex = start;
        this.end = end;
        this.step = step;
    }
    
    next() {
        let result;
        if (this.nextIndex < this.end) {
            result = { value: this.nextIndex, done: false }
            this.nextIndex += this.step;
            return result;
        }
        return {  done: true }
    }
}

class RangeIterable
{
    start = 0;
    end = Infinity;
    step = 1;
    constructor(start = 0, end = Infinity, step = 1)
    {
        this.start = start;
        this.end = end;
        this.step = step;
    }
    
    [Symbol.iterator]() {
        return new RangeIterator(this.start, this.end, this.step);
    }
}

iterable = new RangeIterable(1, 6, 2);

可以看到使用类来实现可迭代对象清晰不少,对C++/Java程序员比较友好。

生成器实现可迭代对象

function* RangeIterableGenerator(start = 0, end = Infinity, step = 1)
{
    for (let value = start; value < end; value += step)
        yield value;
}

iterable = RangeIterableGenerator(1, 8, 2);
// 第一遍循环打印1,3,5,7
for (let v of iterable) console.log(v);
// 第二遍循环什么也不打印
for (let v of iterable) console.log(v);

可以看到生成器来实现可迭代对象多么容易。
上面的生成器等价于下面的类实现:

class RangeIterableAndIterator
{
    start = 0;
    end = Infinity;
    step = 1;
    nextIndex = 0;
    constructor(start = 0, end = Infinity, step = 1)
    {
        this.start = start;
        this.end = end;
        this.step = step;
        this.nextIndex = this.start;
    }
    
    [Symbol.iterator]() {
        return this;
    }
    
    next() {
        let result;
        if (this.nextIndex < this.end) {
            result = { value: this.nextIndex, done: false }
            this.nextIndex += this.step;
            return result;
        }
        return {  done: true }
    }
}
iterable = new RangeIterableAndIterator(1, 8, 2);

如果希望第二遍循环还是打印1,3,5,7, 删除构造函数里面的this.nextIndex = this.start;把这句话添加到[Symbol.iterator]函数去。即:

    [Symbol.iterator]() {
        this.nextIndex = this.start;
        return this;
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值