Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
438 views
in Technique[技术] by (71.8m points)

ecmascript 6 - In JavaScript ES6, what is the difference between an iterable and iterator?

Is an iterable the same as an iterator, or are they different?

It seems, from the specifications, an iterable is an object, say, obj, such that obj[Symbol.iterator] refers to a function, so that when invoked, returns an object that has a next method that can return a {value: ___, done: ___} object:

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)

So in the code above, bar is the iterable, and wah is the iterator, and the next() is the iterator interface.

So, iterable and iterator are different things.

Now, however, in a common example of generator and iterator:

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

In the case above, gen1 is the generator, and iter1 is the iterator, and iter1.next() will do the proper job. But iter1[Symbol.iterator] does give a function that, when invoked, gives back iter1, which is an iterator. So iter1 is both an iterable and iterator in this case?

Besides, iter1 is different from the example 1 above, because the iterable in example 1 can give [1, 3, 5] as many times as wanted using [...bar], while iter1 is an iterable, but since it returns itself, which is the same iterator every time, will only give [1, 3, 5] once.

So we can say, for an iterable bar, how many times can [...bar] give the result [1, 3, 5] -- and the answer is, it depends. And is iterable the same as an iterator? And the answer is, they are different things, but they can be the same, when the iterable uses itself as the iterator. Is that correct?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Yes, iterables and iterators are different things, but most iterators (including all of the ones you get from JavaScript itself, such as from the keys or values methods on Array.prototype or generators from generator functions) inherit from the %IteratorPrototype% object, which has a Symbol.iterator method like this:

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

The result is that all standard iterators are also iterables. That's so you can use them directly, or use them in for-of loops and such (which expect iterables, not iterators).

Consider the keys method of arrays: It returns an array iterator that visits the array's keys (its indexes, as numbers). Note that it returns an iterator. But a common use of it is:

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

for-of takes an iterable, not an iterator, so why does that work?

It works because the iterator is also iterable; Symbol.iterator just returns this.

Here's an example I use in Chapter 6 of my book: If you wanted to loop over all entries but skip the first one and you didn't want to use slice to slice off the subset, you can get the iterator, read the first value, then hand off to a for-of loop:

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);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...