Zuo Lin, Front end development engineer of Wedoctor Front End Technology Department. Super ~ can eat, like swimming, fitness and dancing, love life and technology.

The background,

The story begins like this…

When iterating through groups and object properties, There was some confusion over whether to use the obj.keys(), obj.values() and obj.entries() methods or object.keys (obj), Object.values(obj), object.entries (obj) methods. Without further ado, let’s start with the question:

Need: Want to iterate over an Object and get the property values of the iterate Object implementation: Object.keys(), Object.values() and Object.entries() Accidentally confused the entries(), keys() and values() methods of the array with ~ QAQ

Keys (), values() and entries() traversal methods

Those familiar with ES syntax data structures will be aware that the obj.keys(), obj.values(), and obj.entries() methods are not supported by native object data structures, except arrays, maps, and sets. Keys (obj), Object.values(obj), object.entries (obj) can be used to obtain the traversable properties of native objects to form an array type data structure.

That is, there are two keys(), values(), and entries() methods:

  1. Keys, Object.values, and Object.entries are methods that return an array of all the key/value/value pairs of the parameter Object’s own (not inherited) properties. Can be used for… The of loop traverses;
  2. ES6 provides entries(), keys() and values() — this can be used to iterate through instances of array /Map/Set data structures and returns an Iterator object, which can be used for… The of loop iterates.

Notice two more differences:

  1. The two call syntax is different, obviously;
  2. The former returns an iterable object, while the latter returns a real array.

Did you get dizzy? Let’s start with the first problem — the difference in call syntax

Q1: Object.keys, Object.values and Object.entries methods

In order to distinguish between these two call syntaxes, we must review the prototype chain.

This is because the entries(), keys() and values() methods are the ones that call the prototype object constructor. As you can see from the following diagram, for a normal Object, these three methods are constructor under Object [[prototype]] :

For an array structure, these three methods can be found in the constructor of both the array prototype chain and the object prototype above the prototype chain:

Keys (arr) calls the constructor method from the top of the array prototype chain, whereas arr. Keys (), which is supported by the array itself, calls the methods on the array prototype chain.

That is, objects support only the former calls, while arrays support both:

And we know that in JavaScript, objects are the foundation of all complex structures. It also corresponds to the object prototype structure at the top of the prototype chain of other complex structures. It should now be possible to see why the obj.keys(), obj.values() and obj.entries() methods are not supported on ordinary objects, but there is another question:

Q2: How do you make an object support methods obj.keys(), obj.values(), and obj.entries()?

Theoretically, we can construct any method for an object, so how do we implement the same traversal method as an array? Essentially this method is able to generate a traverser.

let objE = {
  data: [ 'hello'.'world'].keys: function() {
    const self = this;
    return{[Symbol.iterator]() {
        let index = 0;
        return {
          next() {
            if (index < self.data.length) {
              return {
                value: self.data[index++],
                done: false
              };
            }
            return { value: undefined.done: true}; }}; }}}};Copy the code

Above, we created a data object ourselves and implemented its own data.values() method. Meanwhile, we can still call the object.values (data) method on it.

As you can see from the above method, we manually construct an output iterator function in the object by adding symbol. iterator. We’ll discuss the iterator in the next section, but first we’ll discuss the difference between the result returned by the call.

Q3: Two call methods return results: traversers and arrays

The first method returns an array that contains all the key/value/key-value pairs of an Enumerable property of the parameter object itself.

Hit the point!! These three methods return only the object’s own traversable property, which means that an attribute description object’s Enumerable is true.

We can do this by… In loop to achieve the same traversal effect.

2) The second method returns a traverser: as the name implies, the traverser can also satisfy the need for loop traversal.

In essence, an traversator is defined as an interface that provides a unified access mechanism for a variety of different data structures. Let’s look at traversers for different data structures.

3. An Iterator

First of all, we know that there are four main data structures representing “collections” : Array, Object, Map and Set. Here, the objects representing “collections” are such as NodeList Array objects, and traverser can enable us to traverse and access these collections.

In fact, data structures with native Iterator interfaces include Array, Map, Set, String, TypedArray, function arguments objects, and NodeList objects.

Specific Iterator concept can refer to teacher Ruan Yifeng ES6 Introduction Iterator chapter, has been very detailed and clear:

Thus, the Iterator essentially provides a unified access mechanism for all data structures. Of circulation.

For traversal, we already talked about traversal object properties, but here’s another word:

1. Traverse Array data structures such as Array objects, Array, Map, and Set

When using the for… When the of loop iterates over some data structure, the loop automatically looks for the Iterator interface. A data structure is said to be “iterable” whenever the Iterator interface is deployed. ES6 states that the default Iterator interface is deployed in the symbol. Iterator property of a data structure. In other words, a data structure can be considered “iterable” as long as it has the symbol. Iterator property.

2. Obtain the traversable property of the object

Keys, Object.values, and Object.entries only return the Object’s own traversable property, which describes an Object’s Enumerable to indicate whether an Object’s property can be traversed. Iterator: not iterable: Symbol. Iterator: not iterable: Symbol. Iterator: Symbol. Uncaught TypeError: obj is not iterable.

As you can see, arrays and class arrays iterate differently than normal objects, depending on their Iterable and Enumerable properties, respectively.

3. for … of

ES6 introduced for… The of loop is often used instead of for… In and forEach(), and support the new iteration protocol. for… The of statement creates an iteration loop over the iterable, calls the custom iteration hook, and executes the statement for the value of each different attribute.

So the ultimate question: how do you implement symbol. iterator so that ordinary objects can be iterated for? And we actually did that in Q2.

Try to implement a symbol. iterator interface for ordinary objects:

// Common objects
const obj = {
  foo: 'value1'.bar: 'value2'[Symbol.iterator]() {
    Keys does not get the Symbol. Iterator property
    const keys = Object.keys(obj); // Get an array
    let index = 0;
    return {
      next: () = > {
        if (index < keys.length) {
          // The iteration result is not finished
          return {
            value: this[keys[index++]],
            done: false
          };
        } else {
          // End of iteration result
          return { value: undefined.done: true}; }}}; }}for (const value of obj) {
  console.log(value); // value1 value2
};
Copy the code

for… The of loop calls the symbol. iterator method of the data structure inside, for… The scope of the of loop includes arrays, Set and Map structures, some array-like objects (such as Arguments objects, DOM NodeList objects), Generator objects, and strings.

for… The OF loop, a new type of loop introduced in ES6, has the following obvious advantages (on demand) :

  • Has the same for… Same concise syntax as in, but without for… In those disadvantages (disordered, not suitable for traversal groups).
  • Unlike the forEach method, it can be used with break, continue, and return.
  • Provides a unified operation interface for traversing all data structures.

The above are my thoughts on traversal from keys(), values() and entries() traversal methods. If there are any shortcomings, please correct them

Go to the online diagnosis and treatment platform of Wedoctor Internet hospital, make a quick consultation, and find a top three doctor for you in 3 minutes.