【问题标题】:why do we need both iterable and iterator concepts?为什么我们需要可迭代和迭代器概念?
【发布时间】:2016-08-01 07:31:31
【问题描述】:

在 ECMAScript6 中,iterator 是具有 next() 方法的对象,该方法返回具有两个属性的对象:{value, done}。例如:

function createIterator(ra) {
    let i = 0;
    return {
        next() {
            if (i < ra.length)
                return {value: ra[i++],
                        done: false};
            else
                return {value: undefined,
                        done: true};
        }
    };
}

创建了一个迭代器后,发现它本身并不是很有用,因为没有内置的语法可以利用迭代器。相反,必须做以下事情:

    const it = createIterator(['a', 'b', 'c']);
    while (true) {
        const o = it.next();
        if (o.done)
            break;
        else
            console.log(o.value);
    }

另一方面,“Iterable”是一个具有Symbol.iterator 属性的对象,它必须是一个返回迭代器的无参数函数:

function createIterable(ra) {
    let it = createIterator(ra);
    return {
        [Symbol.iterator]() {return it;}
    };
}

...当我们创建一个可迭代对象时,我们终于可以使用for of 语法:

for (let v of createIterable(['a', 'b', 'c']))
    console.log(v);

看上面的代码,“iterable”对象对“iterator”的附加价值并不容易被察觉。那么为什么Javascript需要iterable和iterator这两个独立的概念呢?顺便说一句,这就是Java does as well,所以一定有一些独立于语言的原因,为什么拥有这两个不同的概念是个好主意。

【问题讨论】:

  • 迭代器应该使用yield,而不是return。迭代器实现惰性求值,如 Python 生成器,没错,Java。 Iterables 只是一种标准化如何迭代对象的方法 - 这来自 C++,其中迭代器旨在标准化对象的迭代,其中不清楚要迭代什么。天壤之别。
  • 从概念上讲,“迭代器”包装了迭代操作的当前状态,“可迭代”符号将集合标记为能够提供迭代器。
  • @AkshatMahajan 迭代器和可迭代对象独立存在。生成器(在这方面)只是一种便利。
  • @MarcusJuniusBrutus “当一个对象知道如何一次访问一个集合中的项目时,它就是一个迭代器,同时跟踪它在该序列中的当前位置。” - 来自 Mozilla 文档。 Javascript iterables = Python 中的生成器; JS 生成器是返回迭代器的工厂函数,用词不当——它们与 Python 生成器不对应。迭代器的好处是惰性求值。这就是它存在的原因。
  • @Alnitak 你的评论很有道理。迭代器对象是保存状态的地方,[Symbol.iterator] 方法在每次调用时都会返回一个新的迭代器(具有初始化状态)。

标签: javascript ecmascript-6


【解决方案1】:

从概念上讲,实现“迭代器”接口的对象只是封装了迭代操作的当前状态。一旦该迭代器被使用 (it.done === true),它就不能被重复使用。

“可迭代”对象的 [Symbol.iterator]() 函数在每次调用时都会返回一个 new 迭代器。

在这方面,请注意 OP 的函数,该函数可能存在缺陷,因为由他的 createIterable 函数创建的对象只允许一次性调用其 Symbol.iterator 函数。如果返回的对象被传递给多个for .. of 操作,它将失败。理想情况下应该是:

function createIterable(ra) {
    return {
        [Symbol.iterator]() {
             return createIterator(ra);
        }
    }
}

【讨论】:

  • @MarcusJuniusBrutus 我已经恢复了我的警告 - 您的 createIterable 函数应该可以工作,以便可以重复使用返回的“可迭代”对象。
  • 是的,现在很好。我将在我的问题中留下错误的实现,因为它代表了未来读者的利益,因为您的警告是至关重要的,并有助于突出可迭代和迭代器之间的分工。
  • @MarcusJuniusBrutus 我时差反应了——没有意识到你是 OP! :p
猜你喜欢
  • 2010-11-16
  • 1970-01-01
  • 1970-01-01
  • 2012-03-20
  • 1970-01-01
  • 1970-01-01
  • 2013-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多