Home  >  Article  >  Web Front-end  >  Can es6's for of traverse objects?

Can es6's for of traverse objects?

青灯夜游
青灯夜游Original
2022-05-19 16:11:083548browse

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.

Can es6's for of traverse objects?

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 nameLoop objectWhether the loop can be interruptedIs there a return value##forforforEachArrays, maps, setsdo...whilewhilemapfilterfor...inArray, objectfor...of[Related recommendations:
The length of the loop body can be No return value
Only can be looped, etc. cannot be looped, strings, ordinary objectsNot 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, cannot be cycledmap,set. Can traverse numeric key names, and can also traverse other manually added keys, even keys on the prototype chainCan No return value
Loopable iterable objects, non-loopable ordinary objects (unified data structure traversal) Can No return value
javascript video tutorial

, web front-end

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!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn