An in depth analysis of JavaScript object oriented programming

  • 2021-07-02 23:23:55
  • OfStack

2. Javascript Object-Oriented Programming: Inheritance of Constructors

This section mainly introduces how to generate an instance of "inheriting" multiple objects.

For example, there is now a constructor for an "animal" object.


function Animal(){ 
this.species = " Animals "; 
}

There is also a constructor for the "cat" object,


function Cat(name,color){ 
this.name = name; 
this.color = color; 
} 

How can we make "cat" inherit "animal"?

1. Constructor binding

The simplest way is to bind the constructor of the parent object to the child object using the call or apply method, that is, add 1 line to the child object constructor:


   function Cat(name,color){ 
Animal.apply(this, arguments); 
this.name = name; 
this.color = color; 
} 
var cat1 = new Cat(" Big hair "," Yellow "); 
alert(cat1.species); //  Animals  

2. prototype mode

A more common practice is to use the prototype attribute.

If the prototype object of "cat" points to an instance of Animal, then all instances of "cat" can inherit Animal.


Cat.prototype = new Animal(); 
Cat.prototype.constructor = Cat; 
var cat1 = new Cat(" Big hair "," Yellow "); 
alert(cat1.species); //  Animals  

In line 1 of the code, we point the prototype object of Cat to an instance of Animal.

1.Cat.prototype = new Animal();

It is equivalent to completely deleting the original value of the prototype object and then assigning a new value. But what does line 2 mean?

1.Cat.prototype.constructor = Cat;

It turns out that any one prototype object has an constructor attribute that points to its constructor. That is, the constructor property of the Cat. prototype object points to Cat.

We have deleted the original value of this prototype object in the previous step 1, so the new prototype object has no constructor attribute, so we must add it manually, otherwise the subsequent "inheritance chain" will go wrong. This is what line 2 means.

In a word, this is a very important point, which must be observed when programming. Follow this point below, that is, if you replace the prototype object,

1.o.prototype = {};

Then, the next step must be to add the constructor attribute to the new prototype object and refer this attribute back to the original constructor.

1.o.prototype.constructor = o;

3. Direct inheritance of prototype

Because of the Animal object, the same properties can be written directly to Animal. prototype. Therefore, we can also let Cat () skip Animal () and directly inherit Animal. prototype.

Now, let's rewrite the Animal object first:

1.function Animal(){ }
2. Animal. prototype. species = "animal";

Then, point the prototype object of Cat, and then point to the prototype object of Animal, thus completing inheritance.


Cat.prototype = Animal.prototype; 
CatCat.prototype.constructor = Cat; 
var cat1 = new Cat(" Big hair "," Yellow "); 
alert(cat1.species); //  Animals  

Compared with the first method, this method has the advantages of higher efficiency (no need to execute and establish an instance of Animal) and less memory. The downside is that Cat. prototype and Animal. prototype now point to the same object, so any changes to Cat. prototype will be reflected in Animal. prototype.

Therefore, the above 1 code is actually problematic. Look at line 2

1.Cat.prototype.constructor = Cat;

This sentence actually changes the constructor attribute of the Animal. prototype object!

1.alert(Animal.prototype.constructor); // Cat

4. Use empty objects as mediators

Because of the above disadvantages of "directly inheriting prototype", an empty object can be used as a mediation.


var F = function(){}; 
F.prototype = Animal.prototype; 
Cat.prototype = new F(); 
Cat.prototype.constructor = Cat; 

F is an empty object, so it takes up almost no memory. At this point, modifying the prototype object of Cat does not affect the prototype object of Animal.

1.alert(Animal.prototype.constructor); // Animal

5. Encapsulation function for prototype mode

We encapsulate the above method into a function, which is easy to use.


function extend(Child, Parent) { 
 
var F = function(){}; 
F.prototype = Parent.prototype; 
Child.prototype = new F(); 
Child.prototype.constructor = Child; 
Child.uber = Parent.prototype; 
} 

When used, the method is as follows


extend(Cat,Animal); 
var cat1 = new Cat(" Big hair "," Yellow "); 
alert(cat1.species); //  Animals  

This extend function is how the YUI library realizes inheritance.

In addition, explain point 1. Last line of function body

1.Child.uber = Parent.prototype;

This means setting an uber attribute for the child object, which points directly to the prototype attribute of the parent object. This is equivalent to opening a channel on the child object, which can directly call the method of the parent object. This line 1 is put here only to realize the completeness of inheritance, which is purely standby.

6. Copy inheritance

The above is to use prototype object to realize inheritance. We can also change our thinking and adopt the "copy" method to realize inheritance. Simply put, if all the attributes and methods of the parent object are copied into the child object, can't inheritance be realized?

First, put all the immutable properties of Animal on its prototype object.

1.function Animal(){}
2. Animal. prototype. species = "animal";

Then, write another function to realize the purpose of copying attributes.


function extend2(Child, Parent) { 
var p = Parent.prototype; 
var c = Child.prototype; 
for (var i in p) { 
c[i] = p[i]; 
} 
c.uber = p; 
}

The function is to copy the attribute 11 from the prototype object of the parent object to the prototype object of the Child object.

When using it, write:


extend2(Cat, Animal); 
var cat1 = new Cat(" Big hair "," Yellow "); 
alert(cat1.species); //  Animals  

Related articles: