Home > Web Front-end > JS Tutorial > body text

Detailed introduction to JS inheritance (prototype chain, constructor, combination, prototype, parasitic, parasitic combination, Class extends)

不言
Release: 2018-07-23 10:53:28
Original
1510 people have browsed it

The content of this article is to share with you a detailed introduction to JS inheritance (prototype chain, constructor, combination, prototype, parasitic, parasitic combination, Class extends). It has certain reference value. Friends in need You can refer to it.

To be honest, in the past I only needed to know that "parasitic combinatorial inheritance" was the best, as long as there was an ancestral code template to use. Recently, due to some things, I have been thinking about sorting them out for several weeks. This article uses the content in "JavaScript Advanced Programming" as the skeleton, supplements the relevant content of ES6 Class, and describes inheritance from a perspective that I think is easier to understand. I hope everyone can gain something.

1. Inherit classification

First let’s give an overall impression. As shown in the figure, inheritance in JS can be divided into two parts according to whether the object function is used (mentioned below) (Object.create is a new method in ES5 to standardize this function).

Among them, prototype chain inheritance and prototype inheritance have the same advantages and disadvantages, and constructor inheritance and parasitic inheritance also correspond to each other. Parasitic combination inheritance is based on Object.create, and at the same time it optimizes combination inheritance and becomes a perfect inheritance method. The result of ES6 Class Extends is basically the same as that of parasitic combination inheritance, but the implementation scheme is slightly different.

Let’s get to the point immediately.

Detailed introduction to JS inheritance (prototype chain, constructor, combination, prototype, parasitic, parasitic combination, Class extends)

#2. Inheritance method

The prototype chain inheritance, constructor inheritance, and combination inheritance in the upper half of the picture above have a lot of content on the Internet. This article does not describe it in detail, but only points out the key points. Here is the article "Inheritance in JS (Part 1)" that I think is the easiest to understand. If you are not familiar with the content in the first half, you can read this article first and then come back to continue reading; if you are already familiar with it, you can quickly skip this part. In addition, the first half of the section borrows heavily from an inherited article on the yq front end [1].

2.1 Prototypal inheritance

Core: Use the instance of the parent class as the prototype of the subclass

SubType.prototype = new SuperType() 
// 所有涉及到原型链继承的继承方式都要修改子类构造函数的指向,否则子类实例的构造函数会指向SuperType。
SubType.prototype.constructor = SubType;
Copy after login

Advantages: The parent class method can be reused
Disadvantages:

  • The reference attribute of the parent class will be shared by all subclass instances

  • The subclass cannot pass parameters to the parent class when building an instance

2.2 Constructor inheritance

Core: Copy the contents of the parent class constructor to the subclass constructor. This is the only inheritance among all inheritances that does not involve prototype.

SuperType.call(SubType);
Copy after login

Advantages: Completely opposite to prototype chain inheritance.

  • The reference properties of the parent class will not be shared

  • The subclass can pass parameters to the parent class when building an instance

Disadvantages: The methods of the parent class cannot be reused, and the methods of the subclass instance are created separately each time.

2.3 Combination inheritance

Core: The combination of prototypal inheritance and constructor inheritance combines the advantages of both.

function SuperType() {
    this.name = 'parent';
    this.arr = [1, 2, 3];
}

SuperType.prototype.say = function() { 
    console.log('this is parent')
}

function SubType() {
    SuperType.call(this) // 第二次调用SuperType
}

SubType.prototype = new SuperType() // 第一次调用SuperType
Copy after login

Advantages:

  • The methods of the parent class can be reused

  • The reference properties of the parent class will not be shared

  • The subclass can pass parameters to the parent class when building an instance

Disadvantages:
The constructor of the parent class is called twice, The first time, the name and arr attributes of the parent class are added to the prototype of the subclass. The second time, the name and arr attributes of the parent class are added to the constructor of the subclass, thus overwriting the parameters of the same name in the prototype of the subclass. This overwriting situation causes a waste of performance.

2.4 Prototypal inheritance

Core: The object method of prototypal inheritance is essentially a shallow copy of the parameter object.
Advantages: Parent class methods can be reused
Disadvantages:

  • The reference attributes of the parent class will be shared by all subclass instances

  • Subclasses cannot pass parameters to parent classes when building instances

function object(o){
  function F(){}
  F.prototype = o;
  return new F();
}

var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};

var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");

var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends);   //"Shelby,Court,Van,Rob,Barbie"
Copy after login
ECMAScript 5 standardizes prototypal inheritance through the new Object.create() method. This method accepts two parameters: an object to be used as the prototype of the new object and (optionally) an object to define additional properties for the new object. The Object.create() method behaves the same as the object() method when one parameter is passed in. ——"JAVASCript Advanced Programming"

So the code above can be transformed into

var yetAnotherPerson = object(person); => var yetAnotherPerson = Object.create(person);
Copy after login

2.5 Parasitic inheritance

Core: Use prototypal inheritance to obtain a shallow copy of the target object , and then enhance the ability of this shallow copy.
Advantages and Disadvantages: Only provides one idea, no advantages

function createAnother(original){ 
    var clone=object(original);    //通过调用函数创建一个新对象
    clone.sayHi = function(){      //以某种方式来增强这个对象
        alert("hi");
    };
    return clone;                  //返回这个对象
}

var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};

var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"
Copy after login

2.6 Parasitic Combination Inheritance

Just mentioned that one of the combination inheritance will call the constructor of the parent class twice, causing waste Disadvantages, parasitic combination inheritance can solve this problem.

function inheritPrototype(subType, superType){
    var prototype = object(superType.prototype); // 创建了父类原型的浅复制
    prototype.constructor = subType;             // 修正原型的构造函数
    subType.prototype = prototype;               // 将子类的原型替换为这个原型
}

function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}

SuperType.prototype.sayName = function(){
    alert(this.name);
};

function SubType(name, age){
    SuperType.call(this, name);
    this.age = age;
}
// 核心:因为是对父类原型的复制,所以不包含父类的构造函数,也就不会调用两次父类的构造函数造成浪费
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
    alert(this.age);
}
Copy after login

Advantages and disadvantages: This is a perfect inheritance method.

2.7 ES6 Class extends

Core: The results of ES6 inheritance are similar to parasitic combination inheritance. In essence, ES6 inheritance is a kind of syntactic sugar. However, parasitic combined inheritance first creates the this object of the subclass instance and then enhances it; while ES6 first adds the properties and methods of the parent class instance object to this (so the super method must be called first), and then uses the subclass instance object to The constructor of the class modifies this.

class A {}

class B extends A {
  constructor() {
    super();
  }
}
Copy after login

The specific principle of inheritance in ES6:

class A {
}

class B {
}

Object.setPrototypeOf = function (obj, proto) {
  obj.__proto__ = proto;
  return obj;
}

// B 的实例继承 A 的实例
Object.setPrototypeOf(B.prototype, A.prototype);

// B 继承 A 的静态属性
Object.setPrototypeOf(B, A);
Copy after login

ES6继承与ES5继承的异同:
相同点:本质上ES6继承是ES5继承的语法糖
不同点:

  • ES6继承中子类的构造函数的原型链指向父类的构造函数,ES5中使用的是构造函数复制,没有原型链指向。

  • ES6子类实例的构建,基于父类实例,ES5中不是。

3. 总结

  • ES6 Class extends是ES5继承的语法糖

  • JS的继承除了构造函数继承之外都基于原型链构建的

  • 可以用寄生组合继承实现ES6 Class extends,但是还是会有细微的差别

相关推荐:

Vue中钩子函数的具体介绍

AngularJs自定义指令可以如何来设置以及自定义指令的命名规范

The above is the detailed content of Detailed introduction to JS inheritance (prototype chain, constructor, combination, prototype, parasitic, parasitic combination, Class extends). For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!