JavaScript inheritance details and sample code, and javascript sample code
If you cannot understand some knowledge at the time, you can put it down for the moment. You may understand it later.
A few months ago, with "JavaScript advanced programming (the third edition)", after creating an object, I began to develop inheritance. However, after the prototype chain was completed, I couldn't see it, and my mind was getting messy, then I threw it aside and continued to look at the back. Now that I understand this inheritance during the summer vacation, I will sort out my notes.
Prototype Chaining)
Let's take a look at an article. The author of this article is very good at speaking about it and also has a set of high-definition images. Lol...
Link: [Study Notes] A Small View of the JS prototype chain
Extract a few small sentences from the original article
- The constructor accesses the prototype object through the prototype attribute.
- The instance object accesses the prototype object through the [[prototype] internal attribute, and the browser implements the proto attribute for the instance object to access the prototype object.
- All objects are Object instances, and all functions are Function instances.
- An Object is a constructor. A Function is an instance Object of a Function. A Function is a constructor, but Function. prototype is an Object. An Object is an instance Object of an Object.
Determine the relationship between the prototype and the instance
There are two ways to check the relationship between the prototype and the instance:
Instanceof: instance that determines whether the object is another object
The internal operation mechanism of instanceof is as follows:
Functioninstance_of (L, R) {// L indicates the left expression, and R indicates the right expression varO = R. prototype; // obtain the R display prototype L = L. _ proto __; // obtain the implicit prototype of L while (true) {if (L = null) returnfalse; if (O = L) // here the focus is: if O is strictly equal to L, truereturntrue; L = L is returned. _ proto __;}}
The above code is taken from: in-depth analysis of JavaScript instanceof Operators
IsPrototypeOf (): test whether an object exists in the prototype chain of another object.
For differences between the two methods, see JavaScript isPrototypeOf vs instanceof usage.
Only use prototype chain for inheritance
Disadvantages: 1. The prototype property of the reference type value will be shared by the instance; 2. When creating a child-type instance, parameters cannot be passed to the super-Type constructor.
functionFather(){this.name ="father";this.friends = ['aaa','bbb'];}functionSon(){}Son.prototype = newFather();Son.prototype.constructor = Son;vars1 =newSon();vars2 =newSon();console.log(s1.name);// fatherconsole.log(s2.name);// fathers1.name = "son";console.log(s1.name);// sonconsole.log(s2.name);// fatherconsole.log(s1.friends);// ["aaa", "bbb"]console.log(s2.friends);// ["aaa", "bbb"]s1.friends.push('ccc','ddd');console.log(s1.friends);// ["aaa", "bbb", "ccc", "ddd"]console.log(s2.friends);// ["aaa", "bbb", "ccc", "ddd"]
Only use constructors to implement inheritance
Implementation Method: call the supertype Constructor (use the apply () and call () Methods) within the subtype constructor)
Advantage: solves the problem of referencing type attributes in the prototype, and sub-classes can transmit parameters to the super class.
Disadvantage: subclass instances cannot access the methods defined in the parent class (superclass) prototype, so function reuse is impossible.
FunctionFather (name, friends) {this. name = name; this. friends = friends;} Father. prototype. getName = function () {returnthis. name ;}; functionSon (name) {// Note: To ensure that the Father constructor does not override the attributes of the Son constructor, put the code that calls the Father constructor before the attributes defined in Son. Father. call (this, name, ['aaa', 'bbb']); this. age = 22;} vars1 = newSon ('son1'); vars2 = newSon ('son2'); console. log (s1.name); // son1console. log (s2.name); // son2s1. friends. push ('ccc ', 'ddd'); console. log (s1.friends); // ["aaa", "bbb", "ccc", "ddd"] console. log (s2.friends); // ["aaa", "bbb"] // The subclass instance cannot access method s1.getName () in the parent class prototype; // TypeError: s1.getName is not a functions2.getName (); // TypeError: s2.getName is not a function
Combination Inheritance)
Implementation Method: The prototype chain is used to inherit the prototype attributes and methods, and the constructor is used to inherit the instance attributes.
FunctionFather (name, friends) {this. name = name; this. friends = friends;} Father. prototype. money = "100 k $"; Father. prototype. getName = function () {console. log (this. name) ;}; functionSon (name, age) {// inherit the attributes of the parent class Father. call (this, name, ['aaa', 'bbb']); this. age = age;} // inherit the attributes and Methods Son in the parent class prototype. prototype = newFather (); Son. prototype. constructor = Son; Son. prototype. getAge = function () {console. log (this. age) ;}; vars1 = newSon ('son1', 12); s1.friends. push ('ccc '); console. log (s1.friends); // ["aaa", "bbb", "ccc"] console. log (s1.money); // 100 k $ s1.getName (); // son1s1. getAge (); // 12vars2 = newSon ('son2', 24); console. log (s2.friends); // ["aaa", "bbb"] console. log (s2.money); // 100 k $ s2.getName (); // son2s2. getAge (); // 24
Combination inheritance avoids the defect of using prototype chain or constructor to implement inheritance. It integrates their advantages and becomes the most common inheritance mode in JavaScript, but it is also flawed, the defects of combination inheritance will be mentioned later.
Original Type Inheritance (Prototypal Inheritance)
Implementation idea: Create a new object based on an existing object using the prototype without creating a custom type.
For this purpose, the following function (obj) is introduced)
Functionobj (o) {functionF () {} F. prototype = o; returnnewF ();} varperson1 = {name: "percy", friends: ['aaa', 'bbb ']}; varperson2 = obj (person1 ); person2.name = "zyj"; person2.friends. push ('ccc '); console. log (person1.name); // percyconsole. log (person2.name); // zyjconsole. log (person1.friends); // ["aaa", "bbb", "ccc"] console. log (person2.friends); // ["aaa", "bbb", "ccc"] ECMAScript 5 by adding an Object. the create () method is normalized Type inheritance. When a parameter is input, the Object. create () and obj () Methods behave the same. Varperson1 = {name: "percy", friends: ['aaa', 'bbb ']}; varperson2 = Object. create (person1); person2.name = "zyj"; person2.friends. push ('ccc '); console. log (person1.name); // percyconsole. log (person2.name); // zyjconsole. log (person1.friends); // ["aaa", "bbb", "ccc"] console. log (person2.friends); // ["aaa", "bbb", "ccc"]
You can choose to use this inheritance if you do not need to create constructors in a crowd, but want to keep one object similar to another.
Parasitic Inheritance)
Parasitic inheritance is closely related to the original type inheritance.
Implementation idea: Create a function that is only used to encapsulate the inheritance process. The function enhances the object in some way internally and returns the object.
Functionobj (o) {functionF () {} F. prototype = o; returnnewF ();} functioncreatePerson (original) {// encapsulate the inheritance process varclone = obj (original); // create object clone. showSomething = function () {// enhancement object console. log ("Hello world! ") ;}; Returnclone; // returned object} varperson = {name:" percy "}; varperson1 = createPerson (person); console. log (person1.name); // percyperson1.showSomething (); // Hello world!
Parasitic Combination Inheritance)
Let's talk about the defects of the previous combination inheritance. The biggest problem with combination inheritance is that, under any circumstances, the constructor of the parent class is called twice: When a subclass is created, another time, when the subclass constructor is called, the constructor of the parent class is called inside the subclass constructor.
FunctionFather (name, friends) {this. name = name; this. friends = friends;} Father. prototype. money = "100 k $"; Father. prototype. getName = function () {console. log (this. name) ;}; functionSon (name, age) {// inherit the attributes of the parent class Father. call (this, name, ['aaa', 'bbb ']); // The second call to Father () is actually called when new Son. age = age;} // inherit the attributes and Methods Son in the parent class prototype. prototype = newFather (); // The first time Father () Son is called. prototype. constructor = Son;
The first call made the subclass prototype an instance of the parent class, so that the prototype of the subclass obtained the instance attribute of the parent class; the second call will make the subclass instance also get the instance attribute of the parent class, And the instance attribute of the subclass will shield the attributes with the same name in the subclass prototype by default. Therefore, after these two calls, extra attributes appear in the subclass prototype, and parasitic combined inheritance is introduced to solve this problem.
The idea behind parasitic combined inheritance is that we don't have to call the constructor of the parent class to specify the prototype of the subclass. What we need is nothing more than a copy of the parent class prototype.
Essentially, parasitic inheritance is used to inherit the prototype of the parent class and then return the result to the prototype of the subclass.
Functionobj (o) {functionF () {} F. prototype = o; returnnewF ();} functioninheritPrototype (son, father) {varprototype = obj (father. prototype); // create the prototype object. constructor = son; // enhancement object son. prototype = prototype; // returned object} functionFather (name, friends) {this. name = name; this. friends = friends;} Father. prototype. money = "100 k $"; Father. prototype. getName = function () {console. log (this. name) ;}; functionSon (name, age) {// inherit the attributes of the parent class Father. call (this, name, ['aaa', 'bbb']); this. age = age;} // use the parasitic inheritance to inherit the attributes and Methods inheritPrototype (Son, Father) in the parent class prototype; Son. prototype. getAge = function () {console. log (this. age) ;}; vars1 = newSon ('son1', 12); s1.friends. push ('ccc '); console. log (s1.friends); // ["aaa", "bbb", "ccc"] console. log (s1.money); // 100 k $ s1.getName (); // son1s1. getAge (); // 12vars2 = newSon ('son2', 24); console. log (s2.friends); // ["aaa", "bbb"] console. log (s2.money); // 100 k $ s2.getName (); // son2s2. getAge (); // 24
Advantage: Make the subclass prototype avoid inheriting unnecessary instance attributes in the parent class.
Developers generally think that parasitic combined inheritance is the most ideal Inheritance Method Based on type inheritance.
Last
Finally, we strongly recommend two hard articles.
Javascript-How Prototypal Inheritance really works
JavaScript's Pseudo do Classical Inheritance divity (Wall flip required)
Abstract A hard image of the second article:
After reading it, I can understand the prototype chain in seconds?
The above is the collection of information inherited from JavaScript. We will continue to add relevant information in the future. Thank you for your support for this site!