es6's "for of" cannot traverse objects. Reason: The Iterator interface was introduced in ES6. Only data types that provide the Iterator interface can be traversed using "for-of"; while ordinary objects do not provide an Iterator interface by default, so "for-of" cannot be used for traversal.
The operating environment of this tutorial: Windows 7 system, ECMAScript version 6, Dell G3 computer.
With the continuous development of front-end, many methods of light loop have appeared, such as for, forEach, do..while, for...in, etc. However, these loops also have their own application scenarios. and advantages and disadvantages.
ES6 provides us with a new loop method for...of, which can loop strings, arrays and other array-like objects. As the most common Object object, it stands to reason that it can be looped?
Let’s take a look at the code example below:
{ // 迭代数组 const iterable = ['a', 'b']; for (const value of iterable) { console.log(value); } // output: a b } { // 普通对象 const obj = { a: 'A', b: 'B' } for(const item of obj){ console.log(item) } // Uncaught TypeError: obj is not iterable }
oh no, an error was reported: Uncaught TypeError: obj is not iterable
. Tip: obj is not iterable. Obviously, it is not possible to directly use for...of
to traverse the Object object.
So why can't for...of, which can traverse most data structures, traverse Object objects?
Reason:
Iterator was introduced in ES6. Only data types that provide the Iterator interface can be used to loop through for-of, while Array, Data types such as Set, Map, and certain arrays such as arguments all provide the Iterator interface by default, so they can be traversed using for-of.
For ordinary objects, the for...of structure cannot be used directly, and an error will be reported, prompting obj is not iterable
, which means that ordinary objects do not have an Iterator interface by default. The Iterator interface must be deployed before it can be used.
How to deal with it? Let for-of traverse the object
So the reason is clear, how to solve it? Can it provide an Iterator interface for objects and other data types?
The answer is yes, ES6 also provides the Symbol.iterator attribute. As long as a data structure has this attribute, it will be regarded as having an Iterator interface. , then there is how to implement this interface. The following is the simplest implementation:
newObj[Symbol.iterator] = function(){ let index = 0 , self = this , keys = Object.keys( self ) ; return { next(){ if( index < keys.length ){ return { value: self[keys[index++]] , done: false }; } else{ return { value: undefined , done: true } } } }; };
If you look carefully, you will find that the Symbol.iterator interface is actually a Generator function, then you can simplify the code:
newObj[Symbol.iterator] = function* (){ let keys = Object.keys( this ) ; for(let i = 0, l = keys.length; i < l; i++){ yield this[keys[i]]; } } for(let v of newObj){ console.log( v ); } // 输出结果 // 5 // 6
It is worth noting that Object.keys happens to solve the inheritance problem encountered by for-in before
This meets our expectations and uses for-of to traverse the object, but something seems wrong, we traverse Objects are generally expected to output key and value at the same time. Adjusting the code like this
newObj[Symbol.iterator] = function* (){ let keys = Object.keys( this ) ; for(let i = 0, l = keys.length; i < l; i++){ yield { key: keys[i] , value: this[keys[i]] }; } } for(let v of newObj){ console.log( v ); } // 输出结果 // {key: "e", value: 5} // {key: "f", value: 6}
returns an object, which seems very uncomfortable. Can we try some destructuring assignment? . .
for(let {key, value} of newObj){ console.log(key, value ); } // 输出结果 // e 5 // f 6
This seems perfect. . .
Extended knowledge: The difference between for-of and other loops
Loop object | Whether the loop can be interrupted | Is there a return value | |
---|---|---|---|
| forThe length of the loop body can be |
No return value | |
Only can be looped | Arrays, maps, sets, etc. cannot be looped, strings, ordinary objects Not possible |
No return value | |
If certain conditions are met, it can be looped all the time, at least once |
Yes | No return value | |
If certain conditions are met, the loop can be continued |
Yes | No return value | |
Form a new array member. Only arrays can be looped, strings and ordinary objects cannot be looped, set , map |
Uninterruptible | Returns a new array, does not affect the original array | |
Filtering Array members, only arrays can be looped, strings and ordinary objects cannot be looped, set, map |
cannot be interrupted | returns a new array and does not affect the original array | |
Can be cycled | Array, object, cannot be cycledmap,set . Can traverse numeric key names, and can also traverse other manually added keys, even keys on the prototype chain Can |
No return value | |
Loopable iterable objects, non-loopable ordinary objects (unified data structure traversal) |
Can | No return value |
The above is the detailed content of Can es6's for of traverse objects?. For more information, please follow other related articles on the PHP Chinese website!