preface

Object traversal is a very common operation in Javascript. There are five common methods:

  1. for... in
  2. Object.keys()
  3. Object.getOwnPropertyNames()
  4. Object.getOwnPropertySymbols()
  5. Reflect.ownKeys()

Do you know the difference between the above traversal methods? If you already know the difference, don’t waste your time. If you’re still wondering, take a few minutes to read the following article.

The preparatory work

There are a few things you need to know about object properties:

  • The attribute name can bestringIt could be oneSymbol;
  • Properties can beCan be enumeratedIt can also beAn enumeration;
  • Attributes can be derived fromTheir ownCould also come fromPrototype chain;

We use the following code to create an object that has the corresponding enumerable/non-enumerable string /Symbol attributes for itself and the prototype.

/** * Defines the attributes of the object *@param {*} The target object *@param {*} Key * keys@param {*} The value value *@param {*} Enumerable can enumerate */
function defineProperty (target,key,value,enumerable) {
  Object.defineProperty(target,key,{
    enumerable:!!!!! enumerable, value }); }// Set proto to target's prototype
const target = {};
const proto = {};
target.__proto__ = proto;

defineProperty(target,'self_str_enum'.'self_str_enum'.true);
defineProperty(target,'self_str_not_enum'.'self_str_not_enum'.false);
defineProperty(target,Symbol.for('self_symbol_enum'),Symbol.for('self_symbol_enum'),true);
defineProperty(target,Symbol.for('self_symbol_not_enum'),Symbol.for('self_symbol_not_enum'),false);

defineProperty(proto,'proto_str_enum'.'proto_str_enum'.true);
defineProperty(proto,'proto_str_not_enum'.'proto_str_not_enum'.false);
defineProperty(proto,Symbol.for('proto_symbol_enum'),Symbol.for('proto_symbol_enum'),true);
defineProperty(proto,Symbol.for('proto_symbol_not_enum'),Symbol.for('proto_symbol_not_enum'),false);

/** * Prints the property traversed by the object */
const logKeys = (key,value,target) = > {
  console.log(key);
}

Copy the code

First, we define a defineProperty utility function that adds an attribute to an Object by calling Object.defineProperty. Enumerable is an enumerable parameter that is true. A value of false indicates that the property is non-enumerable. Next, we create a target object and a Proto object, and set the target.__proto__ property to proto, making ProTO the prototype for target. For those who have doubts about this part, you can take a look at the knowledge of JS prototype chain. Next, set the properties for target and Proto. In terms of attribute names, I’ve made semantic names, self_STR_enum for self enumerable string attributes, proto_symbol_not_enum for non-enumerable symbol attributes on the stereotype chain, and so on. Finally, we define a utility function logKeys to print the results of the traversal and use it during the traversal. Here we get an object that contains the string /Symbol enumerable/unenumerable properties of its/prototype.

Now that we’re ready, let’s go through it in these ways:

for… in

Action: Iterates through the enumerable string properties of the object itself and the stereotype

function use_ForIn (target,cb) {
  for (const key in target) {
    cb(key,target[key],target);
  }
}
use_ForIn(target,logKeys);

// Output result:
// self_str_enum
// proto_str_enum
Copy the code

As can be seen from the output, for… The in method iterates through enumerable string attributes on itself and the stereotype, while the Symbol attribute is skipped.

Object.keys()

Function: accepts an object and returns an array of the object’s own enumerable string property names

function use_Object_keys (target,cb) {
  Object.keys(target).forEach(key= > cb(key,target[key],target));
}
use_Object_keys(target,logKeys);

// Output result:
// self_str_enum
Copy the code

As you can see from the output, the Object.keys method only iterates through its own enumerable string properties, while the Symbol and prototype properties are skipped. This API is a limited version of for… The in.

Object.getOwnPropertyNames()

Function: accepts an object and returns an array of the object’s own enumerable and non-enumerable string attribute names

function use_Object_getOwnPropertyNames (target,cb) {
  Object.getOwnPropertyNames(target).forEach(key= > cb(key,target[key],target));
}
use_Object_getOwnPropertyNames(target,logKeys);

// Output result:
// self_str_enum
// self_str_not_enum
Copy the code

Can be seen from the output of the Object. GetOwnPropertyNames way can traverse a string attribute, regardless of whether it is can be enumerated, and the Symbol and prototype attribute are slightly.

Object.getOwnPropertySymbols()

Accepts an object and returns an array of the object’s own enumerable and non-enumerable Symbol property names

function use_Object_getOwnPropertySymbols (target,cb) {
  Object.getOwnPropertySymbols(target).forEach(key= > cb(key,target[key],target));
}
use_Object_getOwnPropertySymbols(target,logKeys);

// Output result:
// Symbol(self_symbol_enum)
// Symbol(self_symbol_not_enum)
Copy the code

Can be seen from the output of the Object. GetOwnPropertySymbols way can traverse its Symbol attribute, regardless of whether it is can be enumerated, and string attributes and prototype were slightly. The API is more like the Object. The getOwnPropertyNames supplement.

Reflect.ownKeys()

Accepts an object and returns an array of the object’s own string and Symbol property names, including non-enumerable properties

function use_Reflect_ownKeys (target,cb) {
  Reflect.ownKeys(target).forEach(key= > cb(key,target[key],target));
}
use_Reflect_ownKeys(target,logKeys);

// Output result:
// self_str_enum
// self_str_not_enum
// Symbol(self_symbol_enum)
// Symbol(self_symbol_not_enum)
Copy the code

As you can see from the output, the reflect.ownkeys method iterates through its own string and Symbol property, whether or not it is enumerable. The return value is equal to the Object. GetOwnPropertyNames (target). The concat (Object. GetOwnPropertySymbols (target))

conclusion

Finally, use a table to summarize, this table will be the above various traversal methods of ability and limitations are shown, feel helpful friends can click 👍.