Before starting the code, you should clearly understand what the purpose of the inheritance and what benefits can bring. Generally speaking, when designing the class, we hope to reduce duplicate code and weaken the coupling between classes. It is difficult to take care of both. We need to determine what method we should take according to the specific conditions and environment. According to our understanding of the inheritance of the face -to -object language, the inheritance will bring a direct strong coupling, but due to its unique flexibility, JS can design a strong coupling and weak coupling code, high efficiency and inefficient code. And what you use depends on the situation.
The following provides three methods of inheritance in JS: class inheritance, prototype inheritance, and mixing. Here is a brief description of the inheritance of the class. The latter two are briefly described in the future. Please pay more attention and guidance. Thank you.
Class form inheritance.
The realization of the inheritance of the JS type depends on the prototype chain. What is the original chain? The object in JS has a attribute prototy. This attribute returns a reference to the object type, which is used to provide a set of basic functions of the class of the object.
It seems to have an impression of Prototype. By the way, we often use code like this.
Copy code code as follows:
var Person = Function () {
this.Name = "liyatang";
};
Person.prototype = {
// You can provide the basic function of Person here
getName: Function () {
Return this.name;
}
}
We put the basic function of the class in the Prototype property, indicating that the reference of the Person object has the XXX function.
After understanding the prototype, you need to understand what the original chain is. When a member (attribute or method) of the visiting object, if the member is not seen in the current object, then JS will find it in the object referred to in the Prototype attribute. Find in the object referred to until found. If not found, it will return to undifined.
So what prompts do the original chain give us? It is easy to think that the primary chain means to allow one class to inherit another class. Just set the subclass's prototype as an instance pointed to the parent class. This binds the members of the parent class to the sub -class, because they will find the parent class when they are not found on the subclass. (The above two paragraphs of words are not rigorous, only described in easy -to -understand words)
Below we need a CHINESE class, and we need to inherit the names and Getname members of the Person class.
Copy code code as follows:
Var Chinese = Function (name, nation) {
// Inheritance, you need to call the constructor of the parent class, you can call it with call, this point to Chinese
// Person can call Person members on this scope
Person.call (this, name);
this.nation = national;
};
Chinese.prototype = Person.prototype;
// It is not the same as before, because the Prototype attribute is covered
//Chinese.prototype = {
// Getnation: Function () {{
// Return this.nation;
//}
//};
// The way in the future will need to be added like this
Chinese.prototype.getNation = Function () {
Return this.nation;
};
The inheritance relationship is established, we call it like this
Copy code code as follows:
var C = New Chinese ("liyatang", "China");
alert (c.getName ()); // liyatang
So the inheritance of the type is completed. Is it really done? Use Firebug to set off points at Alert, and you will find that the original Person.prototype was modified and added the getnation method.
This is because the above code chinese.prototype = Person.prototype; This is a reference type, and the chinese also modified Person. This is not tolerated in itself, and it is not the effect we want.
We can weaken coupling in another object or instance.
Copy code code as follows:
//
//Chinese.prototype = New Person ();
// The second type
// var f = function () {};
//F.prototype = Person.prototype;
//Chinese.prototype = f.prototype;
What are the differences between these two methods? Add a empty function F in the second type, which can avoid an instance of the creation of a parent class, because the parent class may be large, and the parent -class structure function will have some side effects, or a large number of calculations will be performed. Task. So recommend the second method.
At this point, it's over, not yet! There is an attributes of the attributes of the object's attributes, which preserves a reference to a function of a specific object instance. According to this statement, chiese.prototype.constructor should be equal to chinese, which is actually not.
When the prototype chain of the Chiese was set up before memories, we covered the person.prototype off Chiese.prototype. So at this time, Chiese.prototype.ConStructor is Person. We also need to add the following code
Copy code code as follows:
// There is no need to investigate the IF conditions here, knowing Chinese.prototype.constructor = chinese
If (Chinese.prototype.constructor == Object.prototype.constructor) {
Chinese.prototype.constructor = chinese;
}
Turn into the entire code as follows
Copy code code as follows:
var Person = Function (name) {
this.Name = name;
};
Person.prototype = {
getName: Function () {
Return this.name;
}
};
Var Chinese = Function (name, nation) {
Person.call (this, name);
this.nation = national;
};
var f = function () {};
F.prototype = Person.prototype;
Chinese.prototype = f.prototype;
If (Chinese.prototype.constructor == Object.prototype.constructor) {
Chinese.prototype.constructor = chinese;
}
Chinese.prototype.getNation = Function () {
Return this.nation;
};
var C = New Chinese ("liyatang", "China");
alert (c.getName ());
If you can put the inheritance code in a function, it is convenient for the code to reuse, and the last sorting the code is as follows
Copy code code as follows:
Function Extend (Subclass, SuperClass) {{
var f = function () {};
F.prototype = superclass.prototype;
subclass.prototype = new f ();
subclass.prototype.constructor = subclass;
subclass.superclass = SuperClass.prototype; // Add an attribute to the parent class to call the parent class
If (SuperClass.prototype.conStructor == object.prototype.constructor) {
superclass.prototype.constructor = superclass;
}
}
var Person = Function (name) {
this.Name = name;
};
Person.prototype = {
getName: Function () {
Return this.name;
}
};
Var Chinese = Function (name, nation) {
Person.call (this, name);
this.nation = national;
};
extend (Chinese, Person);
Chinese.prototype.getNation = Function () {
Return this.nation;
};
var C = New Chinese ("liyatang", "China");
alert (c.getName ());
Modification after publication:
Under the comments on the first floor, I have a new view of that Extend function. Two methods were proposed when discussing how to set the original chain
Copy code code as follows:
//
//Chinese.prototype = New Person ();
// The second type
// var f = function () {};
//F.prototype = Person.prototype;
//Chinese.prototype = f.prototype;
Although the second way to reduce the construction function of the parent class, the Person.Call (this, name) is used when designing the Chinese class; here is also equivalent to calling the parent class constructor.
However, in the first method, you can reduce the person.call (this, name) in chinese; this part of the code is often forgotten in the subclass. May wish to put this function code in Extend. Just write
Chinese.prototype = new person (); also achieves the same purpose: not strong coupling.
But the forgetfulness is that Chinese.prototype = New Person (); The answer is wrong! Obviously New Person () needs to pass a name parameter. We can't do this part of the EXTEND function, so we have to call the parent -class constructor in the Chinese class. This is also in line with object -oriented ideas.
Therefore, it is still recommended to use the second method.
The first time I wrote about technical articles in this way, basically it is paved according to my own thinking. It is inevitable that there will be some places that are not considered and explained unclear.