laitimes

Why Object.keys and not Object.prototype.keys?

author:Front-end sharing officer

Doubts in development

Sometimes in the process of web development, we will encounter these two functions:

Object.prototype.toString.call()
Object.keys()           

Some front-end partners may wonder why the keys method exists on the object instead of the object. Is there anything special about prototype?

The answer is yes, essentially, the difference between the Object prototype method and the Object static method.

But before we do that, we need to review constructors, object prototypes, and how to create objects.

Constructors and object prototypes

As shown in the figure:

Why Object.keys and not Object.prototype.keys?
  1. The __proto__ property of an object is the prototype object of the object.
  2. The constructor property of the prototype object also points to the object's constructor.
  3. The prototype property of the constructor points to the prototype object of the object.

The object's constructor

Only prototypes have constructors, and the constructor of normal objects inherits from the constructor of their prototype object. For the sake of understanding, we will not mention this pointer to non-prototype objects below.

Prototype chain

In fact, object archetypes and constructors are also objects, and if you put them in the position of "instance objects", they also have their own object archetypes and constructors, and so the archetypal chain (matryoshka) begins.

Why Object.keys and not Object.prototype.keys?

Think about it:

  1. Function 以及 Function. prototype 的__proto__指向哪里?
  2. Object and Object. Where does the __proto__ of prototype point?
  3. Foo (a user-defined constructor) and Foo. Where does the __proto__ of prototype point?

Point as shown in the figure:

Why Object.keys and not Object.prototype.keys?
  1. 所有构造函数都是由 Function 创建的,所以 proto 指向 Function. prototype。
  2. In addition to the Object. prototype, all other prototypes are {}, and the proto of {} obviously points to the object. prototype。
  3. Object. prototype is different from other prototypes in that it is [Object:null prototype]{} instead of {}. Its proto points to null.
  4. null is the base type and does not possess any properties.

There are three ways to create an object

  1. Created using curly braces. This creation method implicitly inherits from the Object. In other words, the effect is the same as a new object. Objects created by ordinary factory functions also fall into this category.
  2. Create using a constructor or class. You need to use the keyword new. and inherits the prototye property of the constructor as the proto of the instance object.
  3. Using Object. create static method. This method takes an object (typeof is the value of Object, so it also allows the parameter to be null) as a prototype for creating the object. If the Object. create's argument is null, then it is the same as Object. The generations of prototypes are comparable. The result of the print is [Object:null prototype]{}.

Prototyping vs. static methods

With the foreshadowing of these basics, I believe that you will soon understand Object. The difference between prototype and object static methods is actually quite simple.

Almost all objects exist on the prototype chain. prototype, therefore, is placed in the Object. prototype can be used by most objects. But:

  1. If the object is created via Object.create(null), then it is the same as Object. prototype object is the same level, and the object cannot be obtained through inheritance. prototype object.
  2. In addition, during the inheritance process, the instance object arrives at the Object. prototype's methods on the prototype chain can often be overridden.

Based on the above two points, we can only avoid calling the methods of the instance object directly, and instead use methods like Object.prototype.xxx.call(obj,... args) to ensure that the prototype method of the object is used.

The Object static method, on the other hand, can be used directly for any object, and it is also shorter.

Arguably, the approach to object prototyping (especially on a long prototype chain) betrays its original design: it can be called to a method on the prototype chain by instance objects.

In the new EcmaScript syntax APIs, there are more static methods than prototype methods, such as the Proxy and Reflect APIs, on the one hand, to avoid the above problems, and on the other hand, to avoid some conflicts (the methods defined by the developers on the prototype are exactly the same as the names of the new syntax). So, it's not hard to understand that more and more APIs will choose to appear as static methods instead of prototype methods.

Author: Good weather

Link: https://juejin.cn/post/7289415627620810815