1

I am a beginner reading the chapter Iterators from the book

JavaScript: The Definitive Guide

I am not able to understand the next() method in the below example from book which is about Creating iterable-based alternative to the filter() method of JavaScript arrays.

// Return an iterable object that filters the specified iterable,
// iterating only those elements for which the predicate returns true
function filter(iterable, predicate) {
    let iterator = iterable[Symbol.iterator]();
    return { // This object is both iterator and iterable
        [Symbol.iterator]() {
            return this;
        },
        next() {
            for(;;) {
                let v = iterator.next();
                if(v.done || predicate(v.value)) {
                    return v;
                }
            }
        }
    };
}

Let's test this function with an array.

let a = [1,2,3,4,5]
let iter = filter(a, x => x>3) // Call the function

// Lets check the returned object of iter.next() method
iter.next() // {value: 4, done: false}
iter.next() // {value: 5, done: false}
iter.next() // {value: undefined, done: true}

I am completely confused about the next() method here. Please help me in understanding it.

Also, I am not able to understand that... the next() method contains an infinite for loop. But what it makes it break that loop. There is no condition like that here.

Thanks in Advance

1 Answer 1

1

Also, I am not able to understand that... the next() method contains an infinite for loop. But what it makes it break that loop. There is no condition like that here.

return breaks the loop.

I am completely confused about the next() method here. Please help me in understanding it.

Here's what it's doing:

  1. It calls next to get the next result object, which it stores in v.
  2. If v.done is truthy, it returns v (breaking the loop). This means the iterator has reached the end of its sequence.
  3. If v.done is falsy, it calls predicate passing in v.value; if predicate returns a truthy value, next returns v (breaking the loop).

So the result is that the iterator returned by that filter function will iterate the values that the predicate returns a truthy value for, and will return a result object with done set to a truthy value when it reaches the end of the input interable.


I haven't read the recent editions of the book (I bought mine something like 15 years ago), but my guess is that the given code is meant to show how you would use an iterator explicitly, and later Flanagan will introduce for-of and generator functions, which provide a simpler means of doing that filter:

function* filter(iterable, predicate) {
    for (const element of iterable) {
        if (predicate(element)) {
            yield element;
        }
    }
}

Live Example:

function* filter(iterable, predicate) {
    for (const element of iterable) {
        if (predicate(element)) {
            yield element;
        }
    }
}

let a = [1,2,3,4,5];
let iter = filter(a, x => x>3); // Call the function

// Lets check the returned object of iter.next() method
console.log(iter.next()); // {value: 4, done: false}
console.log(iter.next()); // {value: 5, done: false}
console.log(iter.next()); // {value: undefined, done: true}

I went back and forth between implicit (for-of, generators) and explicit in Chapter 6 of my recent book JavaScript: The New Toys. I found interleaving them was the best I could do to help get the concepts but also the details across.

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for your clear explanation. It helped me a lot in understanding. I would love to read the book and increase my knowledge :)
I just wanted to ask one more general question. How does the spread operator works with the iterable object that is being returned. For example [...filter(a, x => x>3)] would return [4, 5]. I mean.. how do they work behind the scenes.
Do they keep calling the function and if v is returned, it stores v.value in my array. And.. it keeps calling this continuously till it reach v.value === undefined or done === true
@RakeshPoddar - When you use spread in an array literal ([...something]), it gets the iterator from something and calls it repeatedly, storing the returned values in the new array, until it sees the done flag. (Note: ... isn't an operator. Operators can't do what spread and rest syntax do.)
Thanks a lot for clearing my doubt. I too got some instinct that it must work this way but my terminology of language was cleared fantastically by you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.