Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the meaning of *[Symbol.iterator] in this context

Tags:

I found some code online. I've squashed the original code down into this little excerpt, that when ran, will print 1-20 to the console.

var NumbersFromOne = {   *[Symbol.iterator] () {     for (let i = 1;; ++i) yield i;   } };  var take = function* (numberToTake, iterable) {   let remaining = numberToTake;    for (let value of NumbersFromOne) {     if (remaining-- <= 0) break;     yield value;   } }   var printToTwenty = take(20, NumbersFromOne)  console.log(...printToTwenty); 

Now, I understand that take() is a GeneratorFunction.
When take() is called, it is given an iterator.
The code "...printToTwenty" uses the spread operator to iterate through that function.

I understand that NumbersFromOne is an object. I've come here looking for an explanation of what this part means:

*[Symbol.iterator] () {} 

Declaring generator functions is done like this: function* () {}
So I'm assuming this isn't declaring a generator function.

* also doesn't represent the function name
* also can't be replaced with another operator (/, -, +)

What is the deal with that syntax, and why is the * before [Symbol.iterator]
If placed after, it will not run.
I had considered that *[Symbol.iterator] () is a way to overwrite the existing iterator property, but then wouldn't it say this[Symbol.iterator].

Thanks!

like image 652
Captainlonate Avatar asked May 02 '16 07:05

Captainlonate


People also ask

What does a Symbol iterator mean?

Symbol. iterator is the protocol that makes native objects like Array , Set , and Map iterable by providing a hook into language features like for…of loops and the spread operator. The most obvious use case is in creating new, iterable data structures that are not provided by the language, like a Linked List.

What is Symbol iterator in JS?

A JavaScript iterable is an object that has a Symbol. iterator. The Symbol. iterator is a function that returns a next() function. An iterable can be iterated over with the code: for (const x of iterable) { }

How do you use an iterable iterator?

The iterable protocol In order to be iterable, an object must implement the @@iterator method, meaning that the object (or one of the objects up its prototype chain) must have a property with a @@iterator key which is available via constant Symbol. iterator : [Symbol.

What is the function of iterator?

The primary purpose of an iterator is to allow a user to process every element of a container while isolating the user from the internal structure of the container. This allows the container to store elements in any manner it wishes while allowing the user to treat it as if it were a simple sequence or list.


1 Answers

There are a few things that might make this code look complicated:

It uses the object property shorthand notation. What you're seeing here is actually the following:

var NumbersFromOne = {   [Symbol.iterator]: function* () {     for (let i = 1;; ++i) yield i;   } }; 

Symbol.iterator creates a custom iterator for your NumbersFromOne object.

So your code basically means that the iterator of NumbersFromOne is defined as a generator. Instead of manually having to define a function which returns a next and other properties:

var NumbersFromOne = {   [Symbol.iterator]: function () {     var i = 1;     return {         next: function() {             return { value: i++, done: false };         }     };   } }; 

Returning the generator creates the next function automatically for. This allows you to yield when you need to.

It can then be called as:

const it = NumbersFromOne[Symbol.iterator](); it.next(); // 1 it.next(); // 2 it.next(); // 3 // ... 

Note: Written this way, this iterator never ends! So if you were to call it in a for ... of loop without an end-condition, it would freeze your program.

like image 55
nils Avatar answered Sep 20 '22 00:09

nils