The past and present of JavaScript’s prototype and prototype chain (two)

3.1. Archetypal objects

In the last article, we talked about the prototype attribute, which points to an object, and the object is used to include attributes and methods that can be shared by all instances of a particular type. In the standard, we call this object a prototype object. Prototyping objects are generated by a set of specific rules when creating a new function.

Since there is an attribute of prototype, why did the browser in the last article capture __proto__? According to the introduction in the ECMA-262 fifth edition, the pointer inside the instance is clearly called [[Prototype]], although there is no standard way to access the pointer, but Firefox, Safari, and Chrome support an attribute __proto__ on each object, so the __proto__ you see is actually a access interface of the browser’s own implementation. It’s not the standard set. But in fact, it is better to follow the browser’s design.

Having said so much, ask a question: who is the connection between __proto__ and whom? I can think about it well.

Although [[Prototype]] can not be accessed, the isPrototypeof () method can be used to determine whether there is a relationship between objects, or getPrototypeof () can be used to get the value of the [[Prototype]].

Since the properties of the prototype object can also be accessed in the instantiated object, then what is the way to determine whether the attributes of the access are in the instantiated object or in the prototype object? The answer is isOwnProperty ().

The for-in loop traverses all properties that can be accessed and enumerated by object, whether in the instance or in the prototype. In the 6.2 section of JavaScript advanced programming (Third Edition), there is such a redundancy:

The instance attribute that shields the properties of the prototype (which is about to mark [[Enumerble]] as false) will also be returned in the for-in loop. According to the author’s understanding, if you define a property that is the same as the name in the prototype in the instance property and the attribute is enumerated in the prototype, then for-in will still return the property. This is actually a very obvious proposition because for-in finds the property in an instance, and the attribute is enumerable (unless you manually set it to the enumerated).

It is troublesome to enumerate all enumerated attributes one by one. Fortunately, ES5 provides Object.keys () method to get all enumerated attributes. If you want to get all instance properties, you can use Object.getOwnPropertyNames ().

It has been said that the prototype model has shortcomings, and its biggest disadvantage is its shared characteristics, and any one of the attributes in the prototype object can affect all the objects it instantiated, which causes the phenomenon of “seeking the same and saving the difference”. So we will use the following one more.

3.2. Use constructor mode and prototype mode together.

In combination, of course, all the shared attributes are placed in the prototype object, and all the unique attributes are placed in the constructor, so that the true “seek the same and save the difference”. For example:

Function Animal () {

This.name = name;

This.type = type;

This.say = function () {

Console.log (‘I am a ‘+ this.type);

}

}

Animal.prototype = {{

Constructor: Animal;

FeetCount: 0;

Run: function () {

Console.log (‘I can run’);

}

}

Var dog = new Animal (‘WangWang’,’dog’);

Be careful:

Why does Animal.prototype reassign constructor here?

Children’s shoes combined with an article can think about it!!

Can we consider optimizing the code above to reduce the amount of code? The dynamic prototype mode can be used at this time:

Function Animal () {

This.name = name;

This.type = type;

This.say = function () {

Console.log (‘I am a ‘+ this.type);

}

If (typeof this.run! =’function’) {

Animal.prototype.feetCount = 0;

Animal.prototype.run = function () {

Console.log (‘I can run’);

}

}

}

Var dog = new Animal (‘WangWang’,’dog’);

Be careful:

Why can’t we use the font size of the object in the above example when initializing the prototype here?

Children’s shoes can also be thought for themselves!

In the JavaScript advanced programming (Third Edition), two patterns are also introduced to create objects: the parasitic constructor mode and the Durable constructor pattern, and the details can be referred to books.

4, archetypal chain

Presumably here, you should have been able to guess the implementation principle of the prototype chain. ES5 uses the prototype chain as the main way to implement inheritance (because the function does not have a signature). Interface inheritance cannot be implemented in ES5). The basic idea is to use the prototype to make one reference type inherit the properties and methods of another reference type. Let’s improve the last section of the picture 3:

It can be seen that through [[prototype]] attribute, the prototype object of instance, prototype object and prototype object is concatenate. This connection is prototype chain.

The same prototype chain also has two problems: a problem with a reference type value in a + prototype (that is, the problem just in the 3.1 section) + cannot pass parameters to the supertype constructor when creating an instance of a subtype.

Therefore, the commonly used solutions include the following:

4.2. Combination inheritance

Combination inheritance is sometimes referred to as pseudo classical inheritance. The scheme combines the constructor (reference 4.2.1 section) and the prototype chain. Look at the following examples:

Function Species (name, type) {

This.name = name;

This.type = type;

}

Species.prototype.run = function () {

Console.log (‘I can run! “);

}

Function Animal (name, type, age) {

Species.call (this, name, type);

This.age = 0;

}

Animal.prototype = new Species;

Animal.prototype.constructor = Animal;

Animal.prototype.reportAge = function () {

Console.log (‘My age is’ + this.age);

}

Var dog = new Animal (‘WangWang’,’dog’, 11);

Dog.run ();

Dog.reportAge ();

The prototype chain diagram of the code is as follows:

4.2.1, borrowing constructor

Using the constructor (constructor stealing) (sometimes called a forgery object or classic inheritance), the principle is simple, that is, the supertype constructor is called within the subtype constructor. For example:

Function Species () {

This.colors= [‘red’,’green’];

}

Function Animal (type, name) {

Species.call (this);

This.type = type;

This.name = name;

}

Var dog = new Animal (‘dog’,’WangWang’);

Dog.colors.push (‘black’);

Var cat = new Animal (‘cat’,’MiMi’);

Cat.colors.push (‘yellow’);

Because using the call function method, when the Species superclass is instantiated, the this pointer points to the instantiated subclass, which is equivalent to colors as the attribute of the subclass Animal, so each instance’s colors is its own private property. As follows:

Because by using the call method, we can also pass parameters to the superclass.

Function Species (feet) {

This.colors= [‘red’,’green’];

This.feet = feet

}

Function Animal (type, name, feet) {

Species.call (this, feet);

This.type = type;

This.name = name;

}

The problem caused by this method is also the common disease of the constructor – that is, the method cannot be reused, each instance has its own method of an instance, so it is generally used in the above way.

4.3. Other schemes

In addition to the combination of inheritance, there are three methods, such as prototype inheritance, parasitic inheritance, parasitic combination inheritance, and so on. The following three methods are not much used, so no introduction is made, and the details can be referred to “JavaScript advanced program design (Third Edition)”.

5. Summary

Through this article, from the first simplest object to the constructor pattern and the prototype pattern creation object, we can see the strong vitality of the language and become more and more interesting in the continuous optimization. We have also grasped the way of creating objects from these evolutions, and studied the obscure concepts of archetype and prototype chain. A thorough study of a concept is often about the history of its evolution, so we must know the future and never forget it.

6. Reference

[1] JavaScript advanced programming (Third Edition) sixth chapter

[2] MDN

[3] ES5 standard

Leave a Reply

Your email address will not be published. Required fields are marked *