Inheritance of ES5 in JavaScript

Keywords: Javascript

Since the inheritance of ES6, the inheritance of ES5 has also dropped out of the stage and will not be used in actual development;

Let's take a look at the inheritance of ES6

 1 class Father{
 2             
 3             constructor(a){
 4                 console.log(a);
 5             }
 6             play(){
 7                 console.log("aaa");
 8             }
 9             static run(){
10                 console.log("static");
11             }
12         }
13         class Son extends Father{
14             constructor(){
15                 super();
16             }
17         }
18         var s=new Son();
19         s.play();
20         Father.run()
21         Son.run();

In ES6, you only need to use the extends and super keywords to inherit the methods and properties of the parent class (including static)

There are no keywords in ES5

Inheritance of ES5

There are five ways to inherit ES5:

  1. Object impersonating inheritance
  2. Prototype chain inheritance
  3. Combination inheritance
  4. Archetypal inheritance
  5. Parasitic inheritance (important)
  • Object impersonating inheritance
1 function Father(_r){
 2             this.r=_r;
 3             console.log("aa");
 4             console.log(this.r);
 5         }
 6         Father.a=3;
 7         Father.run=function(){
 8             console.log(Box.a);
 9         }
10 function Son(){
11             Father.call(this,3);//change this Point to, execute the parent constructor and pass a reference to the parent
12        }
13        var b=new Son();//"aa",3
14        b.run();//TypeError

Change this point through call or apply, and execute the constructor of the parent class

Disadvantage: can only inherit the constructor of superclass, can't inherit the method on prototype chain

  • Prototype chain inheritance
 1 function Father(){
 2     console.log("aa");
 3         }
 4 Father.prototype.b=10;
 5         Father.prototype.play=function(){
 6             console.log(this.b);
 7         }
 8         Son.prototype=new Father();
 9         function Son(){
10         }        
11         var b=new Son();
12         b.play();//10

Assign the instantiated object of the parent class to the inheritance implemented on the prototype of the child class

Disadvantages: override the original properties and methods of the subclass, only the properties and methods of the parent class can be executed, and the constructor of the parent class cannot be executed

  • Combination inheritance

The first two kinds of inheritance (impersonation, prototype chain) have their own characteristics. The combination of these two kinds of inheritance is called combination inheritance

 1  function Father(_r){
 2             this.r=_r;
 3             console.log("aa");
 4         }
 5 function Son(_r){
 6             Father.call(this,_r);//To change the parent of this Point to subclass
 7         }
 8 Son.prototype=new Father(3);//Prototype chain inheritance
 9  var c=new Son(10);
10  

The prototype chain is used to inherit the properties and methods of the parent class, and the object is used to pretend to inherit the constructor of the parent class

It looks good, but it's not the perfect way to inherit;

Disadvantages: it will override the original properties and methods of the class, because prototype chain inheritance instantiates the parent class and executes the parent class constructor once in advance; when the child class instantiates the object, it actually executes the parent class constructor twice.

Usage scenario: the subclass originally has no properties and methods, and the parent constructor has no content.

  • Archetypal inheritance

To solve the problem of executing the parent constructor twice, a mediation is used, and the parent constructor will not be executed when inheriting

 1 function Father(_a){
 2             this.a=_a
 3         }
 4         Father.prototype.play=function(){
 5             console.log("aaa");
 6         }
 7             function Agent(){
 8 
 9             }
10             Agent.prototype=Father.prototype;
11             function Son(){
12                 
13             }
14             Son.prototype=new Agent();
15             var o=new Son();
16             o.play();//aaa

Using the Agent class as the intermediary, copying the prototype of the parent class, and then instantiating and inheriting will not execute the constructor of the parent class;

Disadvantage: Although the problem of constructor executing twice is solved, the constructor will not execute once after using this method to inherit.

  • Parasitic inheritance (perfect inheritance)

Encapsulates an extend method, which passes in two parameters, the parent class and the child class

 1 function extend(subClass, supClass) {
 2         function Agent() {}
 3         Agent.prototype = supClass.prototype;
 4         var o = subClass.prototype;
 5         subClass.prototype = new Agent();
 6         if (Object.assign) {
 7           Object.assign(subClass.prototype, o);
 8         } else {
 9           if (Object.getOwnPropertyNames) {
10             var names = Object.getOwnPropertyNames(o);
11             for (var i = 0; i < names.length; i++) {
12               var desc = Object.getOwnPropertyDescriptor(names[i]);
13               Object.defineProperty(subClass.prototype, names[i], desc);
14             }
15           } else {
16             for (var prop in o) {
17               subClass.prototype[prop] = o[prop];
18             }
19           }
20         }
21         subClass.prototype.constructor = subClass; //Prevent subclass constructors from being overridden
22         if (supClass.prototype.constructor === Object) {
23           supClass.prototype.constructor = supClass; //Prevent the constructor of the parent class from being overridden
24         }
25         // Store parent class, convenient to inherit constructor call
26         subClass.prototype.superClass = supClass;
27       }
28 //call
29       function Father(_r) {
30         this.r = _r;
31         console.log("Father");
32       }
33       Father.prototype.play = function () {
34         console.log("play game");
35       };
36       function Ball(_r) {
37         this.superClass.call(this, _r);
38       }
39 40       var s = new Son(10);//Father
41       s.play();//play game

The extend method uses Object.assgin, Object.getOwnPropertyNames, Object.getOwnPropertyDescriptor, and Object.defineProperty, all of which have compatibility problems, so the judgment is made.

This method inherits the advantages of the first four and realizes the perfect inheritance of ES5;

 

Conclusion:

Compared with the inheritance of ES6, ES5 is too cumbersome to be used in the future;

But when interviewing, the interviewer may ask, it's always right to learn more.

Posted by kuliksco on Sun, 17 May 2020 04:06:09 -0700