Object-Oriented Programming (Inheritance)
This blog is the third article of object-oriented programming, JS inheritance. Inheritance, as its name implies, is the acquisition of all kinds of "property" (attributes and methods) of the parents.
How to realize inheritance?
Our JavaScript is quite special, mainly through prototype chains to achieve inheritance.
Following are various ways to realize inheritance: prototype chain inheritance, borrowing constructors, combination inheritance, prototype inheritance, parasitic inheritance and parasitic combination inheritance.
II. Realizing the Way of Inheritance
1. Prototype Chain Approach
As we all know, each constructor has a prototype for storing shared attribute methods.
Principle of prototype chain inheritance: If we want to inherit a parent class, we can point the prototype object of this subclass to the instance of the parent class.
a. Code:
//Create a parent constructor function Father(){ this.fristName = "Father"; } //Adding methods to prototype objects of parent classes Father.prototype.getFatherName = function(){ return this.fristName ; } //Create subclass constructors function Son(){ this.name = 'jack'; } //The key line is to point the prototype object of the subclass to the parent class instance for inheritance Son.prototype = new Father(); //We can also add prototype methods for subclasses Son.prototype.getName = function(){ return this.name; } //Test it and create an instance of a subclass var s1 = Son(); s1.getFaterName(); //Father inherited his father's name!
b. Some special points of attention:
1. We saw above that getName is added to the subclass prototype. After the subclass prototype object points to the parent class instance, it must be followed by this sentence. If it is before, the method will be overwritten. Because a child prototype object points to a parent instance, it is equivalent to rewriting the child prototype object.
2. Adding a method to a subclass prototype cannot be literal, which overrides the prototype object that has inherited the parent class.
c. Inheritance of prototype chains:
Obviously, the inherited attribute methods are all in the prototype objects of the subclasses, so the attribute methods are shared, which obviously does not meet our usual requirements.
2. Borrowing constructors
Borrow? Yes, borrow the constructor of the parent class. How? Then use the call or apply method.
Borrow the constructor principle: call the constructor of the parent class internally when the constructor of the child class is created.
Code demo:
//The parent class (the parent class is relatively speaking, everybody pays attention to oh) function Father(){ this.colors = ['red','green']; } //Subclass function Son(){ //The key line: Invoke the parent constructor internally, and this is an instance of creating Son in the future Father.call(this); } //Test it, inherit the attributes of the parent class, and the attributes will not be shared oh var s1 = new Son(); s1.colors.push('blue'); console.log(s1.colors); ['red','green','blue'] //The colors of the s2 instance will not be affected var s2 = new Son(); console.log(s2.colors); ['red','green']
The borrowed constructor here implements that attributes and methods are not shared, because attributes are in the constructor, not in the prototype object. But it also shows that there is no way to share methods in this way.
3. Combinatorial inheritance (most commonly used)
Combination inheritance = prototype chain inheritance + borrow constructor inheritance, yes, just combine the two methods.
Principle of Composite Inheritance: Attribute Method for Sharing Instances: I inherit from prototype chains; Attribute Method for Private Instances: I borrow constructors (combining the advantages of both)
Code demo:
//Parent class function Father(name){ this.name = name; this.colors = ['red','green']; } //Parent prototype object Father.pototype.sayName = function(){ console.log(this.name); } //Subclass function Son(name,age){ //Borrowing a parent constructor Father.call(this,name); this.age = age; } //Subclass prototypes point to parent instances, prototype chain inheritance Son.prototype = new Father(); Son.prototype.constructor = Son; //Let prototypes of subclasses construct functions only to subclasses Son.prototype.sayAge = function(){ console.log(this.age); } //Create instance objects var s1 = new Son('Mc ry',22); var s2 = new Son('yy',20); //The parent method is inherited and sayName is shared s1.sayName(); //mc ry s2.sayName(); //yy //Inherit colors, each instance private s1.colors.push('blue'); console.log(s1.colors); ['red','green','blue'] console.log(s2.colors); ['red','green']
There may be some doubts: in the prototype chain inheritance, the subclass prototype object points to the instance of the parent class, and should inherit all the attributes and methods. That should be shared, but why not the colors and name attributes?
Reason: When calling a borrowed constructor, attributes are created in a new instance of a subclass, that is, the existing parent attributes in the subclass instance do not need to continue to look up in the prototype object, that is, they are shielded, so they will not be shared.
4. Prototype Inheritance
This is a way proposed by Douglas Crockford, who proposed a function object() to simply implement inheritance without constructors.
Code demo:
//Object function, passing in an object function object(o){ //Create an empty constructor function F(){}; //The prototype object of this empty constructor points to o. F.prototype = o ; //Returns the instance object of F return new F(); }
Reading this code carefully, you can see that this function eventually returns an object that has all the attributes and methods of the incoming object o. Thus the inheritance is realized.
//An object var person = { name : 'ry', sayName : function(){ console.log(this.name); } } //children object inherits all attribute methods of person object var children = object(person);
With the emergence of prototype inheritance, you can inherit the attribute method of another object without creating a constructor. But obviously, the attributes used are shared.
There is an object.create() method in ES5 that does the same thing as object() above.
5. Parasitic Inheritance
In fact, parasitic and prototype are used in object function, but the difference is that new objects in parasitic can add their own methods.
function creatAnother(o){ //Invoke object inheritance o var obj = object(o); //You can also add the method you want obj.sayHi = function (){ console.log('hi'); } //Return this object retrun obj; } //The new object inherits person var anotherPerson = creatAnother(person); //The method of person can be used after inheritance anotherPerson.sayHi(); //"hi"
6. Parasitic Combinatorial Inheritance (Ideal)
Although the above combination mode is the most commonly used, but the pursuit will continue to optimize it. Because there are also some shortcomings in the way of combination:
On the one hand: we can see that the constructor of the parent class is called twice. (Once the prototype chain inherits the prototype object of the neutron class pointing to the parent class instance, and once borrows the constructor)
On the other hand: the confusion is that the prototype of the subclass has all the attributes of the parent class, but we have to rewrite some attributes when we call the subclass constructor.
So the parasitic combination method solves the above problem by replacing the prototype chain inheritance in the combination method with a function.
Code demo:
//It's mainly this function that implements child prototype objects that inherit only attributes from parent prototype objects. function inheritPrototype(subType,superType){ //Using the Object function above, the prototype of the parent class is assigned to the prototype variable var prototype = object(superType.prototype); //Redirect the prototype constructor to a subclass prototype.constructor = subType; //Give prototype to sub prototype object subType.prototype = prototype; } //Rewrite the previous combination inheritance //Parent class function Father(name){ this.name = name; this.colors = ['red','green']; } //Parent prototype object Father.pototype.sayName = function(){ console.log(this.name); } //Subclass function Son(name,age){ //Borrowing a parent constructor Father.call(this,name); this.age = age; } //(This line is replaced by inheritPrototype function) Subclass prototype points to parent instance, prototype chain inheritance inheritPrototype(Son, Father); Son.prototype.sayAge = function(){ console.log(this.age); }
Parasitic combinatorial inheritance is the most ideal way. It makes the subclass constructor inherit the attributes of the parent constructor and the prototype object of the subclass inherit the attributes and methods of the parent prototype object.
Three, summary
1. This blog describes how to realize inheritance in js, there are many ways, but the main way is combination and parasitic combination. After inheritance, we can use the attributes and methods of the parent class, which increases the reusability of the code.
2. Understanding the inheritance role of js: help us to read some of the framework's source code, perhaps this code is a little difficult to understand, I put a lot of comments for you to read together, or that sentence, see it several times, its meaning is self-evident. If you feel you have something to gain, just give me a compliment and pay attention to me.
- Careful friends may find that I have changed the style of the article, similar to the Markdown style, which looks more refreshing and comfortable.
Several articles in the same series:
First article: JavaScript - I found that you are such a JS (1) (first knowledge)
JS -- I found out that you were JS: OOP[1] - (Understanding Object and Object Attribute Types)
JS -- I found out that you are such a JS: OOP[2] - (Create your object)
I found that you are such a JS article summary (click here)
This article is from Blog Garden: http://www.cnblogs.com/Ry-yuan/
Author: Ry
Welcome to reprint, reprint please indicate the source, retain the field.