I have been hard to understand the Inheritance Mechanism of Javascript language. It does not have the concept of \ "subclass \" or \ "parent class \", nor does it have the concept of \ "class \" (class) and \ "instance \" (instance), all rely on a very strange \ "prototype chain \" (prototype chain) mode, to achieve inheritance.
I spent a lot of time learning this part and made many notes. However, they all belong to forced memory and cannot be understood fundamentally.
How to create a class
Suppose there is a class called Person:
The Code is as follows: |
Copy code |
Var Person = function (name, age ){ This. name = name; This. age = age; } Person. prototype. getName = function (){ Return this. name; } |
As shown above: Person represents all people on Earth. Everyone has these two basic attributes: name and age. Now we want to implement a student class, And then we know that the student is also a Person, and students also have attributes such as name and age. The question is, how can we build this relationship?
First, let's take a look at how object-oriented languages are implemented (for example, Actionscrpt3)
Class Students extend Person {}; // very simple, a line of code; more specifically, it is a word -- extend
How can I change to js?
Before explaining the implementation of the Inheritance Mechanism of js, let's take a look at the prototype chain of js:
The Code is as follows: |
Copy code |
Var person = new Person ('converted ed-flw', 21 ); Person. getName (); // "received-flw" |
How is the preceding getName () method executed? First, you will find whether the getName () method is available in the Person function. If not, go to Person. prototype to find it! And then call it. If not, what? Continue to follow the same method along the prototype until the method is found or reached the top of the prototype chain!
For example, there is a constructor called DOG to represent the prototype of a DOG object.
The Code is as follows: |
Copy code |
Function DOG (name ){ This. name = name; } |
Using new for this constructor generates an instance of the dog object.
The Code is as follows: |
Copy code |
Var dogA = new DOG ('taobao '); Alert (dogA. name); // damao |
Note that the this keyword in the constructor represents the newly created instance object.
3. disadvantages of the new operator
One disadvantage of generating instance objects using constructors is that attributes and methods cannot be shared.
For example, in the DOG object constructor, set a common attribute species for an instance object.
The Code is as follows: |
Copy code |
Function DOG (name ){ This. name = name; This. species = 'kenice '; } |
Then, two instance objects are generated:
The Code is as follows: |
Copy code |
Var dogA = new DOG ('taobao '); Var dogB = new DOG ('ermao '); |
The species attributes of these two objects are independent. Modifying one of them does not affect the other.
The Code is as follows: |
Copy code |
DogA. species = 'cat '; Alert (dogB. species); // displays "dogs", not affected by dogA |
Each instance object has its own copy of attributes and methods. This is not only unable to achieve data sharing, but also a great waste of resources.
So: the idea of inheritance: implement the inheritance mechanism through the prototype chain unique to js!
Prototype-based inheritance
1. Direct inheritance implementation
The Code is as follows: |
Copy code |
Var Students = function (name, age, sid ){ Person. call (this, name, age ); This. sid = sid; } Students. prototype = new Person (); // put the Person on the prototype chain of Students to implement the inheritance mechanism. Students. prototype. constructor = Students; Students. prototype. getResults = function (){ // Obtain the score of the student } |
Do not miss the Students. prototype. constructor = Students line !, When defining a constructor, its default prototype is an Object instance, and the constructor attribute of prototype is automatically set to the function itself !!! If you manually set prototype to another object, the new object naturally does not have the contructor value of the original object. Therefore, you need to reset its constructor attribute. For example:
The Code is as follows: |
Copy code |
Var Test = function (){ This. time = "now "; } Console. log (Test. prototype); // Object {} an empty Object Console. log (Test. prototype. constructor); // function () {this. time = "now" ;}, and function itself // If the prototype attribute of Test is changed manually Test. prototype = { SomeFunc: function (){ Console. log ('Hello world! '); } }; Console. log (Test. prototype. constructor); // function Object () {[native code]} |
// Then you will find that the prototype attribute is completely incorrect, so you need to change its constructor point when Manually changing the prototype attribute;
After the test above, we can see why we need to modify the constructor value.
2. encapsulate the inherited function extend
The Code is as follows: |
Copy code |
Function extend (subClass, superClass ){ Var F = function (){}; F. prototype = superClass. prototype; SubClass. prototype = new F (); SubClass. prototype. constructor = subClass; } |
In fact, the functions of this function are only an encapsulation of the above inheritance process. The differences are:
Only inherits the prototype attribute of superClass, and does not inherit the attribute in the superClass constructor;
This method reduces the overhead of removing a new constructor!
Of course, the problem is that we cannot use this function to inherit all attributes of superClass.
Improvement:
// Add a line of code in the Students constructor:
Person. call (this, name, age );
Summary
Using the prototype chain principle of js, we can easily implement the Inheritance Mechanism of js. Although it is not very strict, my goal has been achieved: try to repeat the code once!