Seven ways to deeply understand JavaScript implementation inheritance

Time:2020-5-23

1. Prototype chain inheritance

Core:Prototype a subclass with an instance of the parent

First, we need to know the relationship among the constructor, prototype and instance: the constructor has a prototype object, the prototype object contains a pointer to the constructor, and the instance contains a pointer to the prototype object.

function Father(){
    this.name  ='name of parent class';
}   
Father.prototype.getFatherName = function(){
    console.log ('method of parent');
}

function Son(){
    this.name  ='name of subclass';
}
//If the prototype object of son has methods or properties at this time, the following Son.prototype  =New father(), due to prototype redirection, methods and properties on the prototype will be lost
Son.prototype.getAge = function(){
    console.log ('age of subclass')
}

Son.prototype  =New father(); // core: create an instance of the parent class and assign the instance to the prototype of the child class

Son.prototype.getSonName = function(){
    console.log ('method of subclass');
}

var son = new Son();
son.getFatherName (); // method of parent class
Son.prototype H. proto__ . getfathername = function() {// disadvantage: if there are multiple instances to its parent prototype, they will affect each other
    console.log ('method of subclass changing parent');
}
son.getFatherName (); // method of subclass changing parent class

Disadvantages:

  1. The attributes (private and public) declared by the parent class with this are shared by all instances, and the operations on reference type data among multiple instances will affect each other.
  2. When creating a subclass instance, you cannot pass parameters to the parent constructor.

2. Borrowing constructor inheritance (call)

Core:Use the constructor of the parent class to enhance the instance of the child classCopy the instance property of the parent class to the child class

function Father(name, age){
    this.name = name;
    this.age = age;
}  
Father.prototype.getFatherName = function(){
    console.log ('method of parent');
}

function Son(name, age, job){
    Father.call (this, name, age); // inherited from other
    this.job = job;
}
Var son = new son ('jacky ', 22,' front end development ');
//son.getFatherName(); // Uncaught TypeError: son.getFatherName is not a function

advantage:

  1. Parameters can be passed to the parent class, and the problem of prototype chain inheritance is solved: the parent class property declared with this will be shared by all instances.

Disadvantages:

  1. Only the properties / methods declared by the parent class through this can be inherited, and the properties / methods on the parent class prototype cannot be inherited.
  2. Each subclass instantiation will execute the parent function, redeclare the method defined in the parent class this, so the parent method cannot be reused.

3. Combination inheritance

Core:Combining the above two methods, the prototype chain is used to inherit the prototype properties and methods, and the constructor technology is used to inherit the instance properties

function Father(name, age){
    this.name = name;
    this.age = age;
    this.sex = 'man';
}
Father.prototype.getFatherName = function(){
    console.log ('method of parent class')
}

function Son(name, age, job){
    Father.call (this, name, age); // the second call: when creating a subtype instance
    this.job = job;
}
Son.prototype  =New family(); // first call: when setting the prototype of a subtype instance
Son.prototype.constructor  =Son; // prototype constructor points back to itself 

Var son = new son ('jacky ', 22,' front end development ');
son.getFatherName();
console.log(son)

Seven ways to deeply understand JavaScript implementation inheritance

advantage:

  1. It can inherit the properties of the parent prototype, pass parameters, and reuse.
  2. The constructor property introduced by each new subclass object instance is private.

Disadvantages:

  1. Two calls to the parent function (New fatherfn() and fatherFn.call (this)), causing certain performance loss.
  2. When using subclasses to create instance objects, there are two problems of the same properties / methods in their prototypes.

expand:

The role of constructor

Returns a reference to the object constructor that created the instance object

When we have only instance objects without references to constructors:
In some scenarios, we import and export instance objects through multiple rounds. We don’t know which function the instance is constructed from or the constructor that tracks the instance, which is more difficult. (it mainly prevents errors in one case, that is, you explicitly use the constructor. For example, I don’t know which function instantiates the instance, but I think clone is the only one, so I can — > instance.constructor )
At this time, the constructor reference can be obtained through the constructor property of the instance object

Let instance = new sonfn() // instantiate subclass
export instance;
//Multiple rounds of import + export cause trouble in sonfn tracking, or do not want to import sonfn into the file again
let  fn = instance.constructor

So every timerewriteThe prototype of the function should fix the pointer of the constructor to maintain the consistency of reading the pointer of the constructor

4. Prototype inheritance( Object.create ())

Core: using an empty object as the intermediary, assign an object directly to the prototype of the empty object constructor, and then return the call of this function, which becomes an instance or object that can add properties at will.

/ * Object.create () implementation principle*/
//Cloneobject () performs a shallow copy of the object passed in, pointing the prototype of constructor f directly to the object passed in.
function cloneObject(obj){
  function F(){}
  F. Prototype = obj; // the prototype that will pass in the obj object as an empty function
  Return new f(); // the prototype of this object is the inherited object. You can find the properties of the inherited object through the prototype chain
}

var father = {
    name: 'jacky',
    age: 22,
    Courses: ['front end']
}

// var son1 =  Object.create (father); // same effect
var son1 = cloneObject(father);
son1. courses.push ('back end');

var son2 = cloneObject(father);
son2. courses.push ('full stack');

console.log ( father.courses ); // ["front end", "back end", "full stack"]

advantage:

You do not need to create a custom type to derive a new object from an existing object

Disadvantages:

Same as prototype chain inheritance. Multiple instances share the properties of the inherited object, which may be tampered with; parameters cannot be passed.

5. Parasitic inheritance

Core:On the basis of prototype inheritance, a function is created to encapsulate the inheritance process. The function internally enhances the object in some form (adding some new methods and properties), and finally returns the object.

Use scene: enhance objects in a fixed way.

function createAnother(obj){
    var clone = Object.create(obj);
    clone.skill  =Function() {// to enhance this object in some way
        console.log('run');
    };
    return clone;
}

var animal = {
    eat: 'food',
    drink: 'water'
}

var dog = createAnother(animal);
dog.skill();

Advantage: no custom type is created, because only a shell is set to add a specific attribute / method return object to enhance the object

Disadvantages:

Same as prototype inheritance: prototype chain inherits multiple instances with the same reference type attribute, which may be tampered with or pass parameters

6. Parasitic combinatorial inheritance

Core: implement inheritance by using constructor to pass parameters and parasitic mode

  1. Inherit the properties / methods declared by the parent class this by borrowing the constructor (call)
  2. Inherit method through prototype chain
function Father(name, age){
    this.name = name;
    this.age = age;
}
Father.prototype.getFatherName = function(){
    console.log ('method of parent class')
}

function Son(name, age, job){
    Father.call (this, name, age); // borrow construction inheritance: inherit the parent class to declare properties and methods to the properties of the child class instance through this
    this.job = job;
}

//Parasitic inheritance: encapsulated son.prototype Object prototype inheritance father.prototype And enhanced the incoming objects.
function inheritPrototype(son,father){
    var clone =  Object.create ( father.prototype ); // prototype inheritance: shallow copy father.prototype object
    clone.constructor  =Son; // enhance the object to compensate for the loss of the default constructor property due to overriding the prototype
    son.prototype  =Clone; // specify the object and assign the newly created object to the prototype of the subclass
}
Inheritprototype (son, father); // point the parent prototype to the child

//New subclass prototype property
Son.prototype.getSonName = function(){
    console.log ('method of subclass')
}

Var son = new son ('jacky ', 22,' front end development ');
console.log(son);

Seven ways to deeply understand JavaScript implementation inheritance

  • Compared with combinatorial inheritance, parasitic combinatorial inheritance has the following advantages:
  1. The parent parent constructor is called only once. Instead of calling a constructor to specify the prototype of a subclass, you indirectly let Son.prototype Access to Father.prototype 。
  2. Avoid creating unnecessary and redundant properties on subclass prototype.

Prototype inherits the parent class’s prototype, keeping the prototype chain context unchanged, and instanceof and isprototypeof() can also be used normally.
3. Parasitic combinatorial inheritance is the most mature inheritance method, and it is also the most commonly used inheritance method. It is also the inheritance scheme adopted by many JS libraries.

Disadvantages:

If you want to add attributes and methods to the subclass prototype, you must put them after the inheritprototype () method

7. ES6 extends inheritance (optimal way)

Core: inheritance between classes is realized through the extends keyword, which is clear and convenient. Class is just a grammar sugar, its core idea is still parasitic combinatorial inheritance.

class Father {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  skill() {
    console.log ('skill of parent');
  }
}

class Son extends Father {
  constructor(name, age, job){
    Super (name, age); // call the constructor of the parent class. You can use this keyword only after calling super
    this.job = job;
  }

  getInfo() {
    console.log(this.name, this.age, this.job);
  }
}


Let son = new son ('jacky ', 22,' front end development ');
son.skill (); // skill of parent class
son.getInfo (); // Jacky 22 front end development
  • If the subclass does not define the constructor method, this method will be added by default. The code is as follows. That is, any subclass has a constructor method, whether or not it is explicitly defined.

The subclass must call the super method in the constructor method, otherwise the new instance will be reported wrong. This is because the subclass’s own this object must first be shaped by the constructor of the parent class to get the same instance properties and methods as the parent class, and then processed, plus the subclass’s own instance properties and methods. If the super method is not called, the subclass will not get this object.

The difference between Es5 inheritance and ES6 inheritance

  1. In essence, the inheritance of Es5 is to create the instance object of the subclass first, and then add the method of the parent class to this( Father.call (this) )。
  2. The inheritance of ES6 is to create the instance object this of the parent class first, and then modify this with the constructor of the child class.
  3. Because a subclass does not have its own this object, it must first call the parent’s super () method.

Recommended Today

Configure Apache to support PHP in the Apache main configuration file httpd.conf Include custom profile in

In Apache’s main configuration file / conf/ http.conf Add at the bottom Include “D:workspace_phpapache-php.conf” The file path can be any In D: workspace_ Create under PHP file apache- php.conf file Its specific content is [html] view plain copy PHP-Module setup LoadFile “D:/xampp/php/php5ts.dll” LoadModule php5_module “D:/xampp/php/php5apache2_2.dll” <FilesMatch “.php$”> SetHandler application/x-httpd-php </FilesMatch> <FilesMatch “.phps$”> SetHandler application/x-httpd-php-source </FilesMatch> […]