JavaScript Iterators and Iterables

Pro Members Only

This lesson is available if you have an active subscription.

Alternatively, some member might be able to gift it to you.

If you already have a subscription, you can sign in.

Professional Modern JavaScript Lessons

1.Course Intro
free
⏱️ 1:13
2.Setup & Tooling
free
⏱️ 3:32
3.Debugger Statements and Breakpoints
free
⏱️ 2:17
4.Primitive Data Types and Values
free
⏱️ 3:06
5.JavaScript Variables - let and const
free
⏱️ 4:50
6.Comments in JavaScript
free
⏱️ 2:55
7.JavaScript Identifer Naming
free
⏱️ 2:52
8.Using TypeScript
free
⏱️ 4:26
9.JavaScript String Masterclass
free
⏱️ 9:29
10.JavaScript Boolean Type
⏱️ 6:45
11.Missing Guide to JavaScript Numbers
⏱️ 15:28
12.JavaScript Objects Demystified
⏱️ 13:33
13.Functions in JavaScript
⏱️ 20:25
14.JavaScript Arrays Masterclass
⏱️ 22:31
15.JavaScript If Else Statements and Best Practices
⏱️ 6:13
16.JavaScript Conditional Expressions
⏱️ 8:38
17.JavaScript Loose vs Strict Equality
⏱️ 4:02
18.Truthy vs Falsy in JavaScript
⏱️ 3:44
19.Concept of JavaScript Nullish and Unification
⏱️ 5:51
20.JavaScript Classes - Object Oriented Programming
⏱️ 10:30
21.JavaScript Error Handling and Exceptions
⏱️ 13:21
22.JavaScript Nullish Operators
⏱️ 5:48
23.JavaScript Switch Statement Masterclass
⏱️ 8:07
24.JavaScript For Loop Iteration Simplified
⏱️ 10:59
25.JSON Masterclass
⏱️ 7:59
26.JavaScript While and Do While Loops
⏱️ 2:52
27.JavaScript Date and Time Simplified
⏱️ 13:16
28.this in JavaScript
⏱️ 12:04
29.JavaScript Tagged Templates Masterclass
⏱️ 5:48
30.Promises in JavaScript
⏱️ 10:01
31.JavaScript Async Await Masterclass
⏱️ 9:00
32.JavaScript Symbols Demystified
⏱️ 7:25
33.JavaScript Iterators and Iterables
⏱️ 8:50
34.JavaScript Generators Simplified
⏱️ 9:17
35.JavaScript Prototype - The Secret Guide
⏱️ 11:21
36.JavaScript Set Builtin Data Structure
⏱️ 9:52
37.JavaScript Map Builtin - HashMap Magic
⏱️ 10:38
38.JavaScript Deferred Promise Pattern - withResolvers
⏱️ 3:35
39.Cloning and Deep Copying in JavaScript
⏱️ 3:14
40.JavaScript Async Await Sequencing and Execution Masterclass
⏱️ 10:31
41.JavaScript Memory Management Masterclass
⏱️ 5:26
42.JavaScript WeakMap Demystified
⏱️ 8:58
43.JavaScript bigint Masterclass
⏱️ 5:35
44.JavaScript WeakSet Explained with Examples
⏱️ 7:47
45.JavaScript Regular Expressions Masterclass
⏱️ 17:54
46.JavaScript Weak References Demystified
⏱️ 5:29
47.JavaScript Memory Leaks Demonstrations and Fixes
⏱️ 6:01
48.Semicolon Free Coding in JavaScript
⏱️ 3:46
49.JavaScript Modules Masterclass
⏱️ 11:36

JavaScript Iterators and Iterables

Subscription Required

You must have an active subscription to access this content.
If you already have a subscription, you can sign in.

Iterators

// Iterator
// Object
// next() => {value, done: boolean}
function range(start = 0, end = Infinity, step = 1) {
let value = start;

return {
next() {
const done = value > end;
if (done) { return { value: undefined, done }; }
let result = { value, done };
value += step;
return result;
},
};
}

const iterator = range(0, 2);
console.log(iterator.next()); // { value: 0, done: false }
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
console.log(iterator.next()); // { value: undefined, done: true }

Iterables and for of

// Object
// [Symbol.iterator](): Iterator
console.log(Symbol.iterator); // Symbol(Symbol.iterator)

const array = ['a', 'b', 'c'];

console.log(array[Symbol.iterator]); // [Function: values]

const iterator = array[Symbol.iterator]();

console.log(iterator.next()); // { value: 'a', done: false }
console.log(iterator.next()); // { value: 'b', done: false }
console.log(iterator.next()); // { value: 'c', done: false }
console.log(iterator.next()); // { value: undefined, done: true }

for (const value of array) {
console.log(value); // a, b, c
}

const message = 'hola';

for (const char of message) {
console.log(char); // h, o, l, a
}

const iterator = message[Symbol.iterator]();

console.log(iterator.next()); // { value: 'h', done: false }
console.log(iterator.next()); // { value: 'o', done: false }
console.log(iterator.next()); // { value: 'l', done: false }
console.log(iterator.next()); // { value: 'a', done: false }
console.log(iterator.next()); // { value: undefined, done: true }

Creating Custom Iterables

// Iterator
// Object
// next() => {value, done: boolean}
// Iterable
// Object
// [Symbol.iterator](): Iterator
function range(start = 0, end = Infinity, step = 1) {
let value = start;
const iterator = {
next() {
const done = value > end;
if (done) { return { value: undefined, done } }
let result = { value, done };
value += step;
return result;
},
};
return {
[Symbol.iterator]() {
return iterator;
},
};
}

for (const value of range(0, 10, 2)) {
console.log(value); // 0, 2, 4, 6, 8, 10
}
javascript
typescript
react
playwright

Enjoy free content straight from your inbox 💌

No spam, unsubscribe at any time.

Transcript

00:00

In order to truly appreciate JavaScript generators, we need to look at iterators. And fundamentally, an iterator is an object that has a next method. And this next method should return something with two properties, a value and a done bullion. Let's demonstrate the usage of an iterator by creating a function that will give us one. And of course, the iterator is simply an object that has a next method. And whenever we invoke the next method, we should get back a value And a done bullion, an excellent candidate for an iterator, is a return value of a range function, which sadly is not built into JavaScript. And this is a function that should take a start value and end value and a step

00:35

size and should start iterating at the start and then continue each time implementing with the step till the value becomes more than the end, we kick off the value with the provided start and then we return iterator, which again is simply an object that has a next method. We should stop returning values when the value becomes a greater than the targeted end, and we can determine that as the done bullion where value is greater than end. If this done becomes true, we simply return an object where value is undefined and of course done will be true.

01:05

Otherwise we create a new result object with the current value and of course the done bullion, which will be false. And then for the next iteration, which may or may not happen, we want to increment the value with the provided step. With this value maintenance out of the way, we can simply return our result object and that's it. We successfully manually created our first JavaScript iterator. Let's create an iterator to play around with it by invoking the range function, passing in a start of zero and end of two, and the default step of one, the first time we invoke the iterator next method,

01:37

we get back an object with the value, which is the same as the start. That is a zero. And of course it is not done yet. For two more times when we invoke the next method, we get the value incremented by one and done will still be false. But after that the value becomes greater than the end and therefore we start getting that object value undefined and done too. This means that the iteration is complete and we should really stop bugging the iterator for more values. Iterator by itself is a very simple protocol and becomes really powerful when we put an iterator in a well-defined place inside an object.

02:10

And that is what makes an object iterable. An iterable is an object that will have a property defined by the well-known symbols, symbol iterator. And this property will be a function that should return something that follows the iterator protocol. We've looked at symbols and wellknown symbols before and the symbol iterator is simply a well-known global symbol that has special meaning within JavaScript. And in fact, this is the heart of how iteration works for many of JavaScripts built-ins. As an example, we know that a JavaScript array is Iterable using a four off loop.

02:44

And the secret reason why is simply because array defines a property symbol iterator, which points to a function that will give us back an iterator. And in fact, we can go really crazy and actually invoke it ourselves if you wanted to to get back an instance of the array iterator. And if you invoke the next method a few times, you can see that it behaves in the same fashion as our range iterator every time. It gives us a new value and done false till it is out of values, at which point it gives us value on define and done true. And this magic of getting the symbol dot iterator function invoking that,

03:17

getting the iterator and then looping over the results is exactly what happens behind the scenes when we use a JavaScript four off loop on any given object including a raise. A fun fact worth knowing is that we can actually iterate over a JavaScript string as well. So if we use a four off loop with this message evil, we get back the individual characters and individual iterations, which of course will be H O L N A and no surprise message does have a property defined for symbol iterator, which is a function which we can invoke to get the iterator. And as we invoke next again and again we get back the individual characters with

03:54

done false. And when we run out of characters, we start getting value undefined done. True. It is worth pointing out that we don't have to return value undefined when done is equal to true. It's just a nice convention to follow. You could pretty much drop the value as well when done is true and it would still work. Now that we understand the iterator protocol and how a well-known symbol iterator can make an object iterable, we can actually build our own custom iterable. To recap, an iterator is simply an object that has a next method which gives us back a value in a Dun bullion. And an iterable is simply an object that has a well-known property symbol dot

04:28

iterator, which must be a function that gives us back an iterator. Armed with this knowledge, let's uplift our range function to return an iterable. Instead of returning a simple iterator, we kick things off as normal. We have the range function, which takes a start and in a step and we initialize the value that we intend to return using the start. And then we create a iterator, which is simply an object that has a next method and the next method returns results such that they have a value and a done bullion. The object contained within the iterator is exactly what we previously returned when our range function was only returning an iterator,

05:01

but now we've kicked things up a notch and we are going to return an object that has a well-known property symbol dot iterator, which is going to be a function that returns the iterator and that's it. We've actually created something that can be used in the built-in iteration processes within JavaScript. As an example, we can use the four off loop on a range of zero to 10 with a step size of two, and we should get back the individual values which are zero to 4, 6, 8, and 10. And if we run this code, that is exactly what happens. As we can see in the program output,

05:33

the most common iterable we use in JavaScript is the built-in array. So of course, JavaScript has convenient ways to convert any Iterable into an array. So we've looked at this function which returns an iterable because it returns an object that has a property symbol of iterator, which is a function that gives us an iterator. If you wanted to convert the result of a range in vocation into an array, we could do that quite easily by creating an array, Looping through the results, using four off and pushing the individual values into the array. And this would work. But as you would expect, there are better ways to do this. Cript array comes with a built-in function called from,

06:09

which takes an retriable and returns an array. So you could use this function to take an iterable and convert it into an array, but there is actually special syntax built into the language that makes this even more concise. And we've actually already looked at this when we were looking at arrays and the syntax is the array spread operator. And we've used these triple dots to spread one array into another, but underneath it doesn't really care if what you pass in is an array or any other iterable underneath it simply uses the Iterable protocol, so it'll work with our range function as well. And as you would expect,

06:43

all of these approaches return the same results, but the spread operator is the way to go. What often confuses people is the fact that you can actually create an object that is both an iterator and is iterable. And that's actually important because JavaScript generators create such objects, but it's actually quite easy to do that ourselves even without generators. So we start off with a clean slate of the range function and we've defined the next method in isolation. Let's look at how we can create an iterator, then an iterable, and then combine the two concepts. For an iterator, it's going to be simply an object that has this next method.

07:18

And then for an Iterable, it's going to be an object that has the well-known property symbol iterator, which is a function that gives us an object which has that next method. So there's actually no conflict between the two. And we could create an Iterable iterator that has the properties of the iterator and the properties of the Iterable. And there's actually even an easier way to do this by using the JavaScript disc keyboard, which we looked at in a previous lesson, because the object that contains the symbol dot iterator already has that next property, we can simply return that object by using the this keyboard. And now our range function is something that returns an it iterator.

07:54

Let's play around a bit with the result of a simple range call for people that want a low level access. They can do that by using the result Next method. They get back the values and the done and they can log out the values as long as the done is still false. But of course, most people will not want the slow level access provided by the iterator and instead use the result as an iterable, as an example, using the spread operator to take that iterable and convert it into an array in terms of behavior, both of these things work with the result. It is an iterator and it is an iterable,

08:27

and the only reason why we are covering this is because this is the kind of object that a generator function returns. There is a lot more to Iterable, but honestly, you already know more than you need to because you will most likely be using them transparently with generators, which is what we will look at in a future tutorial. As always, thank you for joining me and I will see you in the next one.

Professional Modern JavaScript

Professional Modern JavaScript

1.Course Intro
free
⏱️ 1:13
2.Setup & Tooling
free
⏱️ 3:32
3.Debugger Statements and Breakpoints
free
⏱️ 2:17
4.Primitive Data Types and Values
free
⏱️ 3:06
5.JavaScript Variables - let and const
free
⏱️ 4:50
6.Comments in JavaScript
free
⏱️ 2:55
7.JavaScript Identifer Naming
free
⏱️ 2:52
8.Using TypeScript
free
⏱️ 4:26
9.JavaScript String Masterclass
free
⏱️ 9:29
10.JavaScript Boolean Type
⏱️ 6:45
11.Missing Guide to JavaScript Numbers
⏱️ 15:28
12.JavaScript Objects Demystified
⏱️ 13:33
13.Functions in JavaScript
⏱️ 20:25
14.JavaScript Arrays Masterclass
⏱️ 22:31
15.JavaScript If Else Statements and Best Practices
⏱️ 6:13
16.JavaScript Conditional Expressions
⏱️ 8:38
17.JavaScript Loose vs Strict Equality
⏱️ 4:02
18.Truthy vs Falsy in JavaScript
⏱️ 3:44
19.Concept of JavaScript Nullish and Unification
⏱️ 5:51
20.JavaScript Classes - Object Oriented Programming
⏱️ 10:30
21.JavaScript Error Handling and Exceptions
⏱️ 13:21
22.JavaScript Nullish Operators
⏱️ 5:48
23.JavaScript Switch Statement Masterclass
⏱️ 8:07
24.JavaScript For Loop Iteration Simplified
⏱️ 10:59
25.JSON Masterclass
⏱️ 7:59
26.JavaScript While and Do While Loops
⏱️ 2:52
27.JavaScript Date and Time Simplified
⏱️ 13:16
28.this in JavaScript
⏱️ 12:04
29.JavaScript Tagged Templates Masterclass
⏱️ 5:48
30.Promises in JavaScript
⏱️ 10:01
31.JavaScript Async Await Masterclass
⏱️ 9:00
32.JavaScript Symbols Demystified
⏱️ 7:25
33.JavaScript Iterators and Iterables
⏱️ 8:50
34.JavaScript Generators Simplified
⏱️ 9:17
35.JavaScript Prototype - The Secret Guide
⏱️ 11:21
36.JavaScript Set Builtin Data Structure
⏱️ 9:52
37.JavaScript Map Builtin - HashMap Magic
⏱️ 10:38
38.JavaScript Deferred Promise Pattern - withResolvers
⏱️ 3:35
39.Cloning and Deep Copying in JavaScript
⏱️ 3:14
40.JavaScript Async Await Sequencing and Execution Masterclass
⏱️ 10:31
41.JavaScript Memory Management Masterclass
⏱️ 5:26
42.JavaScript WeakMap Demystified
⏱️ 8:58
43.JavaScript bigint Masterclass
⏱️ 5:35
44.JavaScript WeakSet Explained with Examples
⏱️ 7:47
45.JavaScript Regular Expressions Masterclass
⏱️ 17:54
46.JavaScript Weak References Demystified
⏱️ 5:29
47.JavaScript Memory Leaks Demonstrations and Fixes
⏱️ 6:01
48.Semicolon Free Coding in JavaScript
⏱️ 3:46
49.JavaScript Modules Masterclass
⏱️ 11:36