1. The introduction

To be clear: JavaScript is not a true object-oriented language, there are no real classes, so we don’t have class inheritance

There are only two ways to implement inheritance ==, call and stereotype chain ==

Before introducing inheritance, let’s introduce some other concepts

2. Three roles of functions

A function with three roles. As a normal function, as a constructor (class), as an object

Function Person (nickname) {var age = 15 when the normal function makes the private attribute this.age = 30 when the constructor makes the instance attribute} person.prototype. age = 50 when the constructor makes the Person.age =100 // When the object makes a static attribute (class attribute)Copy the code

For example: Array.isArray is a class method array. push is an Array prototype method array. toString is an Object prototype method found along the prototype chain

3. Inheritance

Inheritance principle: Use call to inherit properties on instances and use stereotype chains to inherit properties on stereotypes

3.1 Combination Inheritance

const Person = function (name) { this.name = name } Person.prototype.introduce = function(){ Object.entries(this).forEach((item)=>{ console.log(`my ${item[0]} is ${item[1]}`) }) } const Student = function (name,age) {Person. Call (this,name) this.age = age} Student. Prototype = new Person() Increased overhead Student. Prototype. Constructor = Student. / / it can let the Student constructor. The name changed from Person to convenient Student confirmed constructor let Student = New Student (" Ming ", 15) Student. Introduce () inherit to the parent class prototype method at the same time the parent class instance attributes / / my name is xiao Ming / / my age is 15Copy the code

One disadvantage of composite inheritance is that it adds a new parent once, adding an extra cost (think about how much this cost would be if the parent was very large).

3.2 Student. Prototype = new Person(

Let’s take a closer look at this sentence. Why can it achieve prototype chain inheritance

In the last article, we learned that instances can access stereotypes on a class

If a subclass instance has access to its parent’s prototype, can we say that a subclass inherits its parent?

But a subclass instance can only access a subclass prototype, so I can make the prototype of a subclass equal to the instance of the parent class, because the instance of the parent class can access the prototype of the parent class, which is equivalent to the instance of a subclass having access to the prototype of the parent class

Student. Prototype = Person.prototype so the instance can access the parent instance as well

* * yes! In terms of access alone, you’re right. Student. Prototype = null because the parent of the subclass shares the same address and the parent has been changed

3.3 Optimization Principle

Remember 3.1 said that there is one area where prototype chain inheritance can be optimized? After we know the writing method of 3.2 prototype chain inheritance, we have the question,

  1. To really new an object, we actually only need _Proto_ to establish the relationship. Can we not copy the properties of the parent class?
  2. Do I have to new an object? The relationship between instance and class prototype is established by _proto_, I set this thing manually, can’t new?

These are the two directions of optimization

3.4 optimization of 1

The second optimization is to use new to automatically generate _proto_, but we certainly can’t just create a new parent, we create an empty object, and then change the proto_ of that class to point to what we need to inherit

For example, we need to inherit OBJ, which is to access the obJ instance and access the class’s prototype, so that the address of the class’s prototype points to OBJ, so that we can inherit the class as an empty class to reduce overhead

Var create = function(obj){var fn = funcion(){} Reurturn new fn() // generate _proto_}

Var A = create(B);

This approach is implemented by ES6

The object.create () method creates a new Object, using an existing Object to provide the __proto__ of the newly created Object.

const person = { isHuman: false, printIntroduction: function () { console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`); }}; const me = Object.create(person); me.name = "Matthew"; // "name" is a property set on "me", but not on "person" me.isHuman = true; // inherited properties can be overwritten me.printIntroduction(); //My name is Matthew. Am I human? trueCopy the code

3.5 optimization of 2

Instead of new, just change _proto_ to make the subclass prototype point to the superclass prototype

Student. Prototype points directly to Person. Prototype does not point directly to Person

Student. Prototype pointer doesn’t change, it can’t find attribute, it will look for _proto_, I’ll make it point to Person. Prototype

Proto = Person. Prototype

3.6 Summarize optimization

Student. Prototype = new Person(); Student. Prototype = new Person()

Student. Prototype = object.create (person.prototype) We can optimize both by adding an intermediate empty Object (reducing overhead)

You can also add an intermediate property to optimize student.prototype. proto = Person.prototype

Can establish a parent class and child class relationship

4. New stem what

Since new must be used in the creation of a class, let’s talk about what new does, and remember from the relationship between the instance and the class. The two relationship instances are not the instance properties of the class above, and the _proto_ points to the relationship so new does three things 1. Create an object o that inherits the constructor. 2. Set this to o and execute the constructor, returning k 3. Returns an object if k is an object, or o if not

New function new1(func) {var o = object.create (func.prototype) var k = func.apply(o,arguments[1]) return typeof k === 'object'? K: o} const x = new1(Student,[' zhang ']) x.name //' zhang 'x.at //' I am hungry, I want to eat! 'Copy the code

Let’s go back and look at constructor schema inheritance

const Person = function (name) { this.name = name } const Students = function (name) { Person.call(this,name) // This is student instance} const xm = new Students('小 小 ') console.log(xm) //Students {name: "小 小 "}Copy the code

Student executes the code for Person,this is o, and passes name, O. Name =’ Ming ‘, k = undefined 3. Return o, which returns {name:’ xiaoming ‘}

5. Es6 inheritance

class Person {
}
class Student extends person{
}

Copy the code

Compiled in Babel ES2015-loose mode, the source code is as follows

"use strict"; function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; SubClass.__proto__ = superClass; subClass.__proto__ = superClass; } var Person = function Person() {}; var Student = /*#__PURE__*/ function (_person) { _inheritsLoose(Student, _person); function Student() { return _person.apply(this, arguments) || this; } return Student; }(person);Copy the code

In strict mode, The high-level singleton returns a Student, and you can see that the _inheritsLoose method is inherited by the Person constructor +apply

6. Application of inheritance: vUE array mutation method implementation

We know that the array in vue has a mutate method, and the mutate method has a function like push,pop, on the one hand, the array will change, on the other hand, the responsive (suppose the render method is triggered). We need to implement our own push method, and then let the Array in response data _proto_ point to our variation method prototype chain: One thing we need to be clear about our own variation method is that array. proptryoe cannot be modified

Const arrList = ['push', 'pop'] const render = ()=>{console.log(' Render view ')} const proto = object.create (array.prototype) // ForEach ((method)=>{proto[method] = function(){render(); Array.prototype[method].call(this,... Arguments)}}) var data = [1,2,3] data.__proto__ = proto // MVVM Render view, (data [1, 2, 3, 4]) data. The pop () / / response type, rendering the view, (data) [1, 2, 3]. The shift () / / data [2, 3]Copy the code

This allows variations on push pop to intercept using prototype chains, while using inheritance so that other methods are still on array.protorype

7. To summarize

This section introduces the principle of inheritance and optimization in detail, and also analyzes the inheritance syntax sugar of ES6. At the same time introduced the MVVM array borrow inheritance to achieve the use of response type, because my level is limited, if there is anything wrong, welcome to point out the message.