Home > Article > Web Front-end > Introduction to iterators and generators in JavaScript ES6
This article mainly introduces an in-depth understanding of ES6 iterators and generators. The editor thinks it is quite good, so I will share it with you now and give it as a reference. Let’s follow the editor and take a look.
This article introduces an in-depth understanding of ES6 iterators and generators and shares them with everyone. The details are as follows:
Problems with loop statements
var colors = ["red", "green", "blue"]; for(var i=0; i<colors.length; i++){ console.log(colors[i]); }
Before ES6, this standard for loop tracked the index of the array through variables. If multiple loops are nested, multiple variables need to be tracked, the code complexity will be greatly increased, and bugs of incorrect use of loop variables will easily occur.
Iterators were introduced to eliminate this complexity and reduce errors in loops.
What is an iterator
# Let’s first experience using ES5 syntax to simulate creating an iterator:
function createIterator(items) { var i = 0; return { // 返回一个迭代器对象 next: function() { // 迭代器对象一定有个next()方法 var done = (i >= items.length); var value = !done ? items[i++] : undefined; return { // next()方法返回结果对象 value: value, done: done }; } }; } var iterator = createIterator([1, 2, 3]); console.log(iterator.next()); // "{ value: 1, done: false}" console.log(iterator.next()); // "{ value: 2, done: false}" console.log(iterator.next()); // "{ value: 3, done: false}" console.log(iterator.next()); // "{ value: undefiend, done: true}" // 之后所有的调用都会返回相同内容 console.log(iterator.next()); // "{ value: undefiend, done: true}"
Above, we return an object by calling the createIterator() function. This object has a next() method. When the next() method is called, the return format is { value: 1, done : false} result object.
Therefore, we can define it this way: an iterator is a special object with a next() method, and each time next() is called, a result object is returned.
With the help of this iterator object, we will transform the standard for loop at the beginning [Forget about the new for-of loop feature of ES6 for now]:
var colors = ["red", "green", "blue"]; var iterator = createIterator(colors); while(!iterator.next().done){ console.log(iterator.next().value); }
what?, it’s just to eliminate the loop variable, but it requires so much trouble. Isn’t it worth the loss in terms of code?
That's not the case. After all, createIterator() only needs to be written once and can be reused all the time. However, ES6 introduces generator objects, which can make the process of creating iterators easier.
What is a generator
#A generator is a function that returns an iterator, passed the asterisk after the function keyword (*) to indicate that the new keyword yield will be used in the function.
function *createIterator(items) { for(let i=0; i<items.length; i++) { yield items[i]; } } let iterator = createIterator([1, 2, 3]); // 既然生成器返回的是迭代器,自然就可以调用迭代器的next()方法 console.log(iterator.next()); // "{ value: 1, done: false}" console.log(iterator.next()); // "{ value: 2, done: false}" console.log(iterator.next()); // "{ value: 3, done: false}" console.log(iterator.next()); // "{ value: undefiend, done: true}" // 之后所有的调用都会返回相同内容 console.log(iterator.next()); // "{ value: undefiend, done: true}"
Above, we used ES6 generation, which greatly simplified the iterator creation process. We pass an items array to the generator function createIterator(). Inside the function, the for loop continuously generates new elements from the array and puts them into the iterator. The loop stops every time it encounters a yield statement; each time it calls next of the iterator () method, the loop continues to run and stops at the next yield statement.
How to create a generator
The generator is a function:
function *createIterator(items) { ... }
You can use functions Expression writing:
let createIterator = function *(item) { ... }
can also be added to objects, ES5 style object literals:
let o = { createIterator: function *(items) { ... } }; let iterator = o.createIterator([1, 2, 3]);
ES6 style object method abbreviation:
let o = { *createIterator(items) { ... } }; let iterator = o.createIterator([1, 2, 3]);
Iterable object
In ES6, all collection objects (Arrays, Set collections and Map collections) and strings are all iterable objects, and iterable objects are bound to default iterators.
Here comes, the long-awaited new ES6 loop feature for-of:
var colors = ["red", "green", "blue"]; for(let color of colors){ console.log(color); }
for-of loop, which can be used in iterables On the object, the default iterator on the iterable object is used. The general process is: each time the for-of loop is executed, the next() method of the iterable object is called, and the value attribute of the result object returned by the iterator is stored in the variable. The loop will continue to execute this process until the done object is returned. The value of the property is true.
If you only need to iterate the values in an array or collection, using a for-of loop instead of a for loop is a good choice.
Accessing the default iterator
Iterable objects have a Symbol.iterator method. When the for-of loop is performed, the Symbol of the colors array is called. iterator method to obtain the default iterator, this process is completed behind the JavaScript engine.
We can take the initiative to get this default iterator to feel it:
let values = [1, 2, 3]; let iterator = values[Symbol.iterator](); console.log(iterator.next()); // "{ value: 1, done: false}" console.log(iterator.next()); // "{ value: 2, done: false}" console.log(iterator.next()); // "{ value: 3, done: false}" console.log(iterator.next()); // "{ value: undefined, done: true}"
In this code, the array values are obtained through Symbol.iterator The default iterator and used to iterate over the elements in the array. Executing a for-of loop statement in the JavaScript engine is a similar process.
Use the Symbol.iterator property to detect whether the object is an iterable object:
function isIterator(object) { return typeof object[Symbol.iterator] === "function"; } console.log(isIterable([1, 2, 3])); // true console.log(isIterable(new Set())); // true console.log(isIterable(new Map())); // true console.log(isIterable("Hello")); // true
Create an iterable object
When we create an object, add a generator to the Symbol.iterator property to turn it into an iterable object:
let collection = { items: [], *[Symbol.iterator]() { // 将生成器赋值给对象的Symbol.iterator属性来创建默认的迭代器 for(let item of this.items) { yield item; } } }; collection.items.push(1); collection.items.push(2); collection.items.push(3); for(let x of collection) { console.log(x); }
Built-in iterator
The collection objects in ES6, including arrays, Set collections and Map collections, all have three built-in iterators:
entries() returns an iterator whose values are multiple key-value pairs. If it is an array, the first element is the index position; if it is a Set, the first element and the second element are both values.
values() Returns an iterator whose value is the value of the collection.
keys() returns an iterator whose value is all the key names in the collection. If it is an array, the index is returned; if it is a Set, the value is returned (the value of the Set is used as both a key and a value).
不同集合的默认迭代器
每个集合类型都有一个默认的迭代器,在for-of循环中,如果没有显式指定则使用默认的迭代器。按常规使用习惯,我们很容易猜到,数组和Set集合的默认迭代器是values(),Map集合的默认迭代器是entries()。
请看以下示例:
let colors = [ "red", "green", "blue"]; let tracking = new Set([1234, 5678, 9012]); let data = new Map(); data.set("title", "Understanding ECMAScript 6"); data.set("format", "print"); // 与调用colors.values()方法相同 for(let value of colors) { console.log(value); } // 与调用tracking.values()方法相同 for(let num of tracking) { console.log(num); } // 与调用data.entries()方法相同 for(let entry of data) { console.log(entry); }
这段代码会输入以下内容:
"red"
"green"
"blue"
1234
5678
9012
["title", "Understanding ECMAScript 6"]
["format", "print"]
for-of循环配合解构特性,操纵数据会更方便:
for(let [key, value] of data) { console.log(key + "=" + value); }
展开运算符操纵可迭代对象
let set = new Set([1, 2, 3, 4, 5]), array = [...set]; console.log(array); // [1,2,3,4,5]
展开运算符可以操作所有的可迭代对象,并根据默认迭代器来选取要引用的值,从迭代器读取所有值。然后按返回顺序将它们依次插入到数组中。因此如果想将可迭代对象转换为数组,用展开运算符是最简单的方法。
The above is the detailed content of Introduction to iterators and generators in JavaScript ES6. For more information, please follow other related articles on the PHP Chinese website!