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,
- To really new an object, we actually only need _Proto_ to establish the relationship. Can we not copy the properties of the parent class?
- 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.