在JavaScript ES6中,可迭代和迭代器之间有什么区别?

问题描述 投票:6回答:1

可迭代与迭代器相同,还是不同?

[似乎,from the specifications,一个可迭代对象是一个对象,例如,obj,因此obj[Symbol.iterator]引用了一个函数,因此,当调用该函数时,它返回一个对象,该对象具有一个next方法,该方法可以返回一个{value: ___, done: ___}对象:

function foo() {
    let i = 0;
    const wah = {
        next: function() {
            if (i <= 2) return { value: (1 + 2 * i++), done: false }
            else return { value: undefined, done: true }
        }
    };
    return wah;     // wah is iterator
}

let bar = {}        // bar is iterable

bar[Symbol.iterator] = foo;

console.log([...bar]);             // [1, 3, 5]   
for (a of bar) console.log(a);     // 1 3 5 (in three lines)

因此在上面的代码中,bar是可迭代的,wah是迭代器,next()是迭代器接口。

因此,可迭代和迭代器是不同的东西。

但是,现在在生成器和迭代器的常见示例中:

function* gen1() {
    yield 1;
    yield 3;
    yield 5;
}

const iter1 = gen1();

console.log([...iter1]);                           // [1, 3, 5]
for (a of iter1) console.log(a);                   // nothing

const iter2 = gen1();
for (a of iter2) console.log(a);                   // 1 3 5 (in three lines)

console.log(iter1[Symbol.iterator]() === iter1);   // true

在上述情况下,gen1是生成器,iter1是迭代器,并且iter1.next()将做适当的工作。但是iter1[Symbol.iterator]确实提供了一个函数,该函数在调用时会返回iter1,它是一个迭代器。那么在这种情况下iter1既是可迭代的,又是迭代器?

[此外,iter1与上面的示例1不同,因为示例1中的可迭代项可以使用[1, 3, 5]给出[...bar]所需的次数,而iter1是可迭代项,但是由于它返回了自身,每次都是相同的迭代器,只会给出[1, 3, 5]一次。

所以我们可以说,一个可迭代的[...bar]可以给出结果[1, 3, 5]多少次-答案取决于。并且可迭代与迭代器相同吗?答案是,它们是不同的东西,但是当可迭代对象将自身用作迭代器时,它们可以是相同的。正确吗?

javascript ecmascript-6 iterator iterable
1个回答
2
投票

是,iterables迭代器是不同的东西,但是大多数迭代器(包括从JavaScript本身获得的所有迭代器,例如生成器函数的生成器)都从%IteratorPrototype% object继承,像这样的Symbol.iterator方法:

[Symbol.iterator]() {
    return this;
}

结果是所有标准迭代器也是可迭代的。这样一来,您可以直接使用它们,也可以在for-of循环等中使用它们(它们期望可迭代,而不是迭代器)。

考虑数组的keys方法:它返回一个访问数组键(其索引为数字)的数组迭代器。请注意,它返回一个iterator。但是它的常见用法是:

for (const index of someArray.keys() {
    // ...
}

[for-of需要一个可迭代,而不是一个迭代器,那为什么行得通呢?

之所以有效,是因为迭代器也是可迭代的; Symbol.iterator仅返回this

这是我在本书的第6章中使用的示例:如果您想遍历所有条目但跳过第一个条目,并且不想使用slice分割子集,则可以获取迭代器,读取第一个值,然后切换到for-of循环:

const a = ["one", "two", "three", "four"];
const it = a[Symbol.iterator]();
// Skip the first one
it.next();
// Loop through the rest
for (const value of it) {
    console.log(value);
}

相反,并不是所有的迭代器都是迭代器。数组是可迭代的,但不是迭代器。字符串,地图和集合也是如此。

© www.soinside.com 2019 - 2024. All rights reserved.