Writing in the front
This article mainly discusses the ES6 Iterator, the purpose is to understand its concept, function, and existing applications, and finally learn to put into practice.
Iterator is a pretty big feature in ES6, and it’s the building block on which many other features operate.
Why is Iterator so high up?
Let’s start with a variable
var arr = ['red'.'green'.'blue'];
Copy the code
This is an ordinary array. If I want to get each item of its data, what should I do?
It’s not that easy, just do a for loop, and if you’re feeling low, do a forEach.
Ok, pull the code right away
//forcyclefor(var i=0; i<arr.length; i++){ console.log(arr[i]); } / /forEacth arr.forEach(item=>{ console.log(item); }); / / results slightlyCopy the code
Ok, nothing wrong.
So let’s go ahead and look at the code below. Given a string, what if I want to print every character?
var str='1234567890';
Copy the code
Seriously? It’s ridiculously simple.
You can do it for in, you can do it for loop, you can do it like an array.
Pull the code right away
//for in
for(var s instr){ console.log(str[s]); //s is the attribute name [key]} // convert to arrayfor(var i =0; i<str.length; i++){ console.log(str[i]); } / / or converted to an Array Array. The prototype. Slice. Call (STR);Copy the code
However, for in is not used to fetch data. It iterates through all the enumerable properties of the object, both on itself and on the prototype chain, so this is not safe.
emmm…. That’s all right. Let’s move on.
Take a look at the following code, given a map object, and output each item of its data.
var map = new Map();
map.set('zhang'.'1000w');
map.set('liu'.'200w');
map.set('sun'.'100w');
Copy the code
ForEach is fine.
map.forEach((val,key)=>{
console.log(val,key);
})
Copy the code
I’ve read so many questions so ridiculously simple that I’m probably going to flip the table and leave. Please wait and read down slowly.
Found the problem
Ok, so in the last few simple problems, all we did was get each of them.
Of course, there’s a lot of ways to do it, there’s a lot of ways to implement it, for loops, forEach, for in.
But have you found a problem, or we look at it from a higher dimension, in fact, these methods are not universal, that is to say, the above sets of data can not use a unified traversal method for data acquisition.
ForEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach = forEach
Ok, there’s nothing wrong with that.
But each time you have to transform, encapsulate, and possibly hack prototypes.
Is there a better, universal way to make it more comfortable for developers to use?
The answer is yes, it didn’t come with ES5, it came with ES6.
NB for of
This way of uniformly traversing different data structures is es6’s for of loop.
The for of loop is very similar to the old for loop. It’s just a new syntax.
Quoting ruan da Da’s book in a sentence, I believe that a look will know.
ES6 uses C++, Java, C#, and Python to introduce for… Of circulation. As a unified way to traverse all data structures.
The key is unity, another is direct value, simplify operations, do not need to declare and maintain what variables, data conversion.
“For of” is a “for of” loop.
Why can for of have this capability, can provide a unified way of data acquisition for different data structures.
Is for of really so powerful, and what are the mechanics behind it?
For of isn’t really powerful, it’s just a new ES6 syntax.
Not all objects can use “for of”. Only objects that implement the Iterator interface can use “for of” to iterate over values.
So “for of” is just syntactic sugar, and the real hero is Iterator.
What ? Iterator…..
– Iterator An Iterator
Iterator is an interface designed to provide a unified data access mechanism for different data structures. The Iterator interface is designed primarily for… To make a purchase.
Iterator has been around for years in many backend languages, such as Java, C++, C#, etc.
Since it is an interface, how do we implement the interface? What are the implementation rules?
Since there is no concept of an interface in javascript, we can understand it as a special kind of object-iterator object, and the methods that return this object are called iterator methods.
First it is an object that has a next method that returns a result value each time it is called.
The resulting value is an object containing two properties, value and done.
Value indicates the returned value, done is Boolean and indicates whether the collection has been traversed or if there is any data available, true if there is no data available, and false otherwise.
In addition, a pointer to the current collection location is maintained internally, and each time the next method is called, the pointer is moved back one position (think of it as an array index).
Look at the code implementation
function getIterator(list) {
var i = 0;
return {
next: function() {
var done = (i >= list.length);
var value = !done ? list[i++] : undefined;
return {
done: done, value: value }; }}; } var it = getIterator(['a'.'b'.'c']);
console.log(it.next()); // {value: "a".done: false}
console.log(it.next()); // {value: "b".done: false}
console.log(it.next()); // {value: "c".done: false}
console.log(it.next()); // "{ value: undefined, done: true }"
console.log(it.next()); // "{ value: undefined, done: true }"
console.log(it.next()); // "{ value: undefined, done: true }"
Copy the code
The code above is a mock implementation derived from the basic concept of iterators.
getIterator
Method returns an object-an iterable- Object has a
next
Method,next
Methods hold Pointers internally through closuresi
The value of each callnext
methodsi
The value of all+ 1
. - Then according to the
i
Retrieves data from an array asvalue
, and then determine by indexdone
The value of the. - when
i=3
When the index exceeds the maximum value of the array, no data can be returnedtrue
, traversal is complete.
iterable
At this point we have a general idea of Iterator and how to create an Iterator object. But what does he have to do with “for of”?
For of operation mechanism
When for of executes, the engine automatically calls the iterator methods on the object during the loop, executes the iterator object’s next method in turn, and assigns the value returned by Next to the variables in for of to get the specific value.
I think the above sentence contains an important message – “iterator methods on objects”.
Implement iterables
How can an iterator method exist on an object?
ES6 specifies that whenever you deploy the Iterator interface to an object’s properties, in the form of adding a Symbol. Iterator property to the object, which points to an Iterator method, the Iterator returns a special object-iterator object.
The object that deploys this property and implements the iterator method is called an iterable.
At this point, the object is iterable, which means it can be iterated over by for of.
Symbol.iterator, which is an expression that returns the iterator property of the Symbol object, which is a predefined special value of type Symbol.
For example
Normal objects cannot be traversed by “for of”. Eating them directly will cause an error.
var obj = {};
for(var k of obj){
}
Copy the code
Obj is not an iterable object.
So let’s make an object iterable, according to the protocol, which is the implementation.
IterableObj deploys the symbol. iterator property on the iterableObj object, and then creates an iterator method for it, using the iterator rules described above.
Var iterableObj = {items:[100,200,300], [symbol.iterator]:function(){
var self=this;
var i = 0;
return {
next: function() {
var done = (i >= self.items.length);
var value = !done ? self.items[i++] : undefined;
return {
done: done, value: value }; }}; }} // Walk through itfor(var item of iterableObj){ console.log(item); / / 100200300}Copy the code
That’s it. The above object is an iterable and can be consumed by for of.
Iterator native application scenarios
Going back to the beginning of iterating strings, arrays, and maps using for of, we didn’t deploy the Iterator interface for them, but we could still use for of.
This is because some objects in ES6 already have this interface deployed by default, so you don’t need to do anything to iterate over values using for of.
Don’t believe it? I don’t want you to say-letter. I want me to say-letter.
Let’s see if we can get their iterators.
An array of
Var arr=[100,200,300]; var iteratorObj= arr[Symbol.iterator](); // Get the iterator method and return the iterator object console.log(iteratorobj.next ()); console.log(iteratorObj.next()); console.log(iteratorObj.next()); console.log(iteratorObj.next());Copy the code
string
The Iterator interface is also deployed by default because the values of the string themselves are ordered and have array-like properties that allow access through indexes.
var str='abc'; var strIteratorObj = str[Symbol.iterator](); // Get the iterator console.log(striteratorobj.next ()); console.log(strIteratorObj.next()); console.log(strIteratorObj.next()); console.log(strIteratorObj.next());Copy the code
Or just look at whether the property is deployed on the prototype.
The arguments array class
Arguments inside the function is an array of classes. It also supports for of because it also deploys the Iterator interface internally.
We all know that objects do not deploy this interface by default, so the arguments attribute is not on the prototype, but on the object itself.
function test(){
var obj = arguments[Symbol.iterator]();
console.log( arguments.hasOwnProperty(Symbol.iterator));
console.log( arguments);
console.log(obj.next());
}
test(1, 2, 3);Copy the code
In summary, the objects that have Iterator deployed by default include arrays, strings, sets, maps, and array-like objects (like Arguments objects and DOM NodeList objects).
Code verification is a routine, not to say.
Iterator serves another purpose
Is there anything else Iterator can do besides provide a uniform way to access data from different data structures?
That’s data customizability, because we can control the value of the iterator at will.
For example, the array itself is iterable, and we can override its default iterator.
Var arr = [100200300];for(var o of arr){
console.log(o);
}
Copy the code
The for of array defaults to the following output
After our transformation
Var arr = [100200300]; arr[Symbol.iterator]=function(){
var self=this;
var i = 0;
return {
next: function() {
var done = (i >= self.length);
var value = !done ? self[i++] : undefined;
return {
done: done, value: value }; }}; }for(var o of arr){
console.log(o);
}
Copy the code
Why is the object not deployed by default
Objects can have various properties, unlike arrays where values are ordered.
Therefore, we do not know how to determine the order of their traversal, so we need to manually implement according to the situation.
extension
The for of the interrupt
We all know that a regular for loop can be broken at any time, but what about for of?
The answer is yes, for of is both for and forEach.
In addition to the next method, iterators have two optional return and throw methods.
If the for of loop exits prematurely, the return method is automatically called. Note that the return method must have a value, and the value must be an Object.
Ps: Exits by throwing an exception, which is executed firstreturn
Method throws an exception.
Var iterableObj = {items:[100,200,300], [symbol.iterator]:function(){
var self=this;
var i = 0;
return {
next: function() {
var done = (i >= self.items.length);
var value = !done ? self.items[i++] : undefined;
return {
done: done,
value: value
};
},
return(){
console.log('Early exit');
return{// An object must be returneddone:true}}}; }}for(var item of iterableObj){
console.log(item);
if(item===200){
break; }}for(var item of iterableObj){
console.log(item);
throw new Error();
}
Copy the code
The ps:throw method is not used here. See you in a future article.
More than a for of
Is there any syntax in ES6 other than the Iterator method that automatically calls an object when executing for of?
Deconstruction assignment
The symbol. iterator method is called by default when destructuring an iterable.
// String var STR ='12345';
var [a,b]=str;
console.log(a,b); // 1 2
//map
var map = new Map();
map.set('我'.'front end');
map.set('is'.'technology');
map.set('who'.'quack');
map.set('the writer'.'zz_jesse'); var [d,e]=map; console.log(d,e); / / /"我"."Front end"] ["Yes"."Technology"]...Copy the code
Similarly, if a normal object is deconstructed, an error is reported.
Because ordinary objects are not iterable.
var [d,e]={name:'zhang'};
Copy the code
Destruct assignment from a custom iterable.
var iterableObj = {
items:['red'.'green'.'blue'],
[Symbol.iterator]:function(){
var self=this;
var i = 0;
return {
next: function() {
var done = (i >= self.items.length);
var value = !done ? self.items[i++] : undefined;
return {
done: done, value: value }; }}; } } var [d,e]=iterableObj; console.log(d,e); / / red and greenCopy the code
The value of the deconstructed assignment is the return value of the iterator object’s next method, in order.
Extended operator
Execution of extended operators (…) It also calls its symbol. iterator method by default, which converts the current iteration object to an array.
// String var STR ='1234'; console.log([...str]); / / / / [1, 2, 3, 4] into array map object var map = new map ([[1, 2], [3, 4]]). Map [...] / [[1, 2], [3, 4] / /setObject varset= new Set ([1, 2, 3]); Set [...] / / [1, 2, 3]Copy the code
Generic objects cannot be converted to arrays.
var obj={name:'zhang'}; [.. obj] / / an errorCopy the code
As a data source
As data sources, such as API methods that accept an array, they call their own iterators by default.
For example, Set, Map, and array. from
Var arr=[100,200,300]; var arr=[100,200,300]; arr[Symbol.iterator]=function(){
var self=this;
var i = 0;
return {
next: function() {
var done = (i >= self.length);
var value = !done ? self[i++] : undefined;
return {
done: done,
value: value+'Front-end technology'// Notice here}; }}; }for(var o of arr){ console.log(o); } // 100 front-end technology lake // 200 front-end technology lake // 300 front-end technology lakeCopy the code
Coverage completed
/ / generatedsetObject varset = new Set(arr);
Copy the code
// Call the array. from method array. from(arr);Copy the code
Yield * keywords
Yield * is followed by a traversable structure that also calls iterator functions when executed.
let foo = function* () { yield 1; Yield * (2 and 4]; yield 5; };Copy the code
Yield needs to be highlighted, and will be covered in more detail in the next section.
Determines whether an object is iterable
Since the rules for iterables must deploy the symbol. iterator property on the object, we can basically use this genus to determine whether the object is an iterable, and then know whether we can use the for of value.
function isIterable(object) {
return typeof object[Symbol.iterator] === "function";
}
console.log(isIterable('abcdefg')); // true
console.log(isIterable([1, 2, 3])); // true
console.log(isIterable("Hello")); // true
console.log(isIterable(new Map())); // true
console.log(isIterable(new Set())); // true
console.log(isIterable(new WeakMap())); // false
console.log(isIterable(new WeakSet())); // false
Copy the code
conclusion
The emergence of ES6 brings many new data structures, such as Map and Set. Therefore, a unified data acquisition method for for the convenience of data acquisition is added. When for of is executed, the engine automatically calls the iterator of the object to evaluate it.
Not all objects support this approach, but only those that implement the Iterator interface. Such objects are called iterables.
According to the iterable protocol, the iterator protocol can be implemented.
In addition to unified data access, you can also customize the content of the data you get, as long as you need it.
An iterator is a method that returns an iterator object.
An iterable is an object that deploys the Iterator interface and has the correct Iterator methods.
ES6 in many places are used Iterator, usually can pay more attention to observe, think more step.
It’s the end and the beginning
By now we have been able to customize the iterator according to the rules of the iterator, but the implementation process is a bit complicated, after all, we need to maintain the internal pointer, there is a lot of logic processing, inevitably error.
Is there a more elegant way to do it?
Yes, that’s -generator-generator.
let obj = {
* [Symbol.iterator]() {
yield 'hello';
yield 'world'; }};for (letx of obj) { console.log(x); } / /"hello"
// "world"
Copy the code
As you can see, it’s very compact and doesn’t take much code to generate an iterator.
It has more magical powers than just syntactic sugar for generating iterators.
So fun ability is bound to pick a pick, but it is late today, stay up late hurt the body, this time to fix Iterator.
Next time with Generator.
practice
If you find this article useful, try doing the exercises below to improve your understanding, and then leave your answers in the comments.
- Write an Iterator object.
- Define an iterable.
- Tell me about you
Iterator
Understanding, summative output.
reference
Es6.ruanyifeng.com/#docs/itera…
Developer.mozilla.org/zh-CN/docs/…
www.cnblogs.com/xiaohuochai…
One last thing
I am creating a pure technical exchange group for beginners and intermediate front-end developers, with the goal of learning, communicating, thinking and improving their abilities. Because learning alone is not as good as learning together, and only with more communication can we make progress faster.
-
My ideal model is to let one person learn one technology in depth in each period, and then relay it to everyone, which is similar to a sharing class, so that learning efficiency can be improved exponentially.
-
Or you can follow the sequence of questions in the question bank. Each person can think about one question every day and give a summative output, so as to improve his/her skills and expression ability.
-
In this group, you don’t need to worry about your lack of ability or whether the problem is too small to say. You can speak out boldly and let more people analyze it together. It doesn’t matter if you make mistakes.
If you want to join, please pay attention to the public number “front-end technology river’s lake”, reply “into the group”, I pull you into the group.
I recommend you to pay attention to my public number “front-end technology river’s Lake”, get more original selected articles, in addition in my spare time I made an interview question bank website, used to collect the front end questions, the purpose is to save time, improve efficiency, fragments of time brush questions. I recommend you to pay more attention.
In order to find the entrance of the question bank conveniently and not get lost, the entrance is bound to the independent menu of the official account.
Site entrance – big front-end interview brush questions – http://bigerfe.com/
Finally, I hope this article can give you some help. If there are any mistakes in this article, please refer to them in the comments section.
If this article inspires you, please like it and follow it.
See “Front-end Technology”