What I want to introduce today is how to generate an instance that "inherits" multiple objects.
For example, there is now a constructor for the "animal" object,
function Animal(){
this.species = "Animal";
}
There is also a constructor for the "cat" object,
Function Cat(name,color){
this.name = name;
this.color = color;
}
How to make "cat" inherit "animal"?
1. Constructor binding
The simplest method is probably to use the call or apply method to bind the constructor of the parent object to the child object, that is, in the child object constructor Add a line to the function:
Function Cat(name,color) {
Animal.apply(this, arguments);
this.name = name;
this.color = color;
}
var cat1 = new Cat("大毛","黄");
alert(cat1.species); // Animals
2. prototype mode
The more common approach 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); // Animal
code In the first line, we point Cat's prototype object to an Animal instance.
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 the second line mean?
Cat.prototype.constructor = Cat;
It turns out that any prototype object has a constructor attribute pointing to its constructor. In other words, 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, so the new prototype object does not have a constructor attribute, so we must add it manually, otherwise there will be problems with the "inheritance chain" later. This is what the second line means.
In short, this is a very important point and must be followed when programming. The following follows this point, that is, if the prototype object is replaced,
o.prototype = {};
Then the next step must be to add the constructor attribute to the new prototype object and point this attribute back to the original Constructor.
o.prototype.constructor = o;
3. Directly inherit prototype
Since in the Animal object, the unchanged attributes can be written directly to Animal.prototype. Therefore, we can also let Cat() skip Animal() and inherit Animal.prototype directly.
Now, let’s rewrite the Animal object first:
function Animal(){ }
Animal.prototype.species = "Animal";
Then, point the prototype object of Cat to the prototype object of Animal, thus completing the inheritance.
Cat.prototype = Animal.prototype;
Cat .prototype.constructor = Cat;
var cat1 = new Cat("Big Hair","Yellow");
alert(cat1.species); // Animal
Compared with the previous method, the advantage of this method is that it is more efficient (no need to execute and create an instance of Animal) and saves memory. The disadvantage is that Cat.prototype and Animal.prototype now point to the same object, so any modifications to Cat.prototype will be reflected in Animal.prototype.
So, the above code is actually problematic. Please look at the second line
Cat.prototype.constructor = Cat;
This sentence actually changes the constructor property of the Animal.prototype object!
alert(Animal.prototype.constructor); // Cat
4. Use empty objects as intermediaries
Since "directly inherit prototype" has the above shortcomings, you can use an empty object Objects act as intermediaries.
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 time, modifying the prototype object of Cat will not affect the prototype object of Animal.
alert(Animal.prototype.constructor); // Animal
5. Encapsulation function of prototype mode
We encapsulate the above method into a function for ease of 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); // Animal
This extend function is how the YUI library implements inheritance.
Also, let me explain something. The last line of the function body
Child.uber = Parent.prototype;
means to set an uber attribute for the child object, which directly points to the prototype attribute of the parent object. This is equivalent to opening a channel on the child object, and you can directly call the method of the parent object. This line is placed here just to achieve the completeness of inheritance and is purely for backup purposes.
6. Copy inheritance
The above uses prototype objects to implement inheritance. We can also change our thinking and purely use the "copy" method to implement inheritance. To put it simply, if you copy all the properties and methods of the parent object into the child object, wouldn't inheritance also be achieved?
First of all, put all the immutable properties of Animal on its prototype object.
function Animal(){}
Animal.prototype .species = "Animal";
Then, write a function to achieve the purpose of attribute copying.
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 of this function is to copy the attributes in the prototype object of the parent object to the prototype object of the Child object one by one. When using
, write like this:
extend2( Cat, Animal);
var cat1 = new Cat("Big Hair", "Yellow");
alert(cat1.species); // Animal
Not finished yet, please continue reading Part 3 "Non-Constructor Inheritance".
(End)