Combing the Core Knowledge Points of JS--Prototype and Inheritance

Posted by Alex C on Wed, 22 May 2019 19:42:38 +0200

Introduction

As mentioned in the previous section, some people think JavaScript is not really an object-oriented language. In classic object-oriented languages, you might prefer to define class objects, then you can simply define which classes inherit which classes, JavaScript uses a different implementation, and inherited object functions are inherited not by copying, but by prototype chains (usually).It is called prototypal inheritance.

Inheritance Mode

When it comes to inheritance, you first have to understand what it is that you inherit.For ease of understanding, I personally classify attributes (including methods) into common and private attributes.Private attributes such as name or ID card are unique to everyone.Common attributes are attributes or methods that can be shared, such as hobby attributes, eating methods.

Inheritance of private properties (constructor + call)

This is simpler, private attributes use constructors and call s or apply

const Person = function (name) {
        this.name = name
    }
const Students = function (name) {
        Person.call(this,name)
    }
const xm = new Students('Xiao Ming')
console.log(xm)  //Students {name:'Xiao Ming'}

Inheritance of Public Properties

There are a few pits in it, so listen to me.
It's certainly true to inherit public attributes through a prototype chain, but when we design, there is a principle that subclasses need to have their own prototypes, and the parent must have its own prototypes, so that child instances can't find attributes on their own prototypes until they find them.
Subclass.prototype =parent class.prototype is certainly not possible. Although the method of the parent prototype can be inherited, the prototype of the subclass and the prototype of the parent class are the same. Adding a method to the prototype of the subclass is equivalent to adding a method to the prototype of the parent class.so we should have a buffer.

Subclass instances---->Subclass prototypes------->Intermediate objects--------->Parent prototypes//Accessible along arrows, behaving in accordance with our design principles

The most common is to use an instance of the parent class as this intermediate object.

Children.prototype = new Parent()    

But there's something wrong with this.The parent class is instantiated once.If the parent class is particularly complex, such as axios, there is a lot of extra overhead.

Let's see what the intermediate object does, it actually only serves as an isolation and prototype redirection.You can do this with an empty object

//Implement Buffering
var fn = function() {}
fn.prototype = Parent.prototype
Children.prototype = new fn()

In fact, this is the implementation of Oject.create()

//Oject.create()
Object.create = function(obj){
    var fn = funcion(){}
    fn.prototype = obj
    reurturn new fn() 
}

Ultimate Inheritance Solution

Now we have to inherit both private and public attributes.

    const Person = function (name) {
        this.name = name
    }
    Person.prototype.eat = function () {
        console.log('i am hungry,i want to eat!')
    }
    const Student = function (name) {
        Person.call(this,name)
    }
    Student.prototype = Object.create(Person.prototype)   //Watch out here!Sequelae of prototype redirection
    const xm = new Student ('Xiao Ming')
    xm.name //'Xiao Ming' 
    xm.eat() //i am hungry,i want to eat!
    console.log(xm)
    //Student {name:'Xiao Ming'}
    //  name:'Xiao Ming'
    //  __proto__: Person
    //      _u proto_u: //This layer is an empty object with only one u proto_u attribute pointing to the prototype of Person
    //          eat: ƒ ()
    //            constructor: ƒ (name)
    //            __proto__: Object

But here xm.constructor.name // Person
Here, because the construtor was not reset after the prototype redirection, the XM itself had no construtor and could only find the empty object we created, and the empty object had no construtor so it went up and found that the construtor on Person.prototype was Person
So the solution is simple, just reset the constructor when rewriting the prototype chain

...
var temObj =  Object.create(Person.prototype)
temObj.constructor = Student
Student.prototype =temObj
...
 xm.constructor.name // Student OK done  

What did new do

Now that new has to be used in creating classes, let's talk about what new does.

1. Create an object o inheritance constructor
2. Make this of the constructor o and execute the constructor, setting the return value to k
3. If k

//Copy 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 San'])
x.name //'Zhang San'
x.eat //'i am hungry,i want to eat!'

Let's go back and analyze constructor pattern inheritance

const Person = function (name) {
        this.name = name
    }
const Students = function (name) {
        Person.call(this,name) //this is a student instance
    }
const xm = new Students('Xiao Ming')  //Analyze what's been done here
console.log(xm)  //Students {name:'Xiao Ming'}

1. Let the empty object o inherit Students(o has access to the Students prototype)
2.student executes, executes Person's code, this is o, and passing in name, o.name='Xiaoming'returns k as undefined
3. Return o, that is, {name:'Xiaoming'}

I wrote this today, but it's not over yet...

es6 Inheritance

in

DefnePrototype in mvvm

Three roles for objects

Static properties, methods.Private properties, methods

Comprehensive Training

summary

Topics: Javascript axios Attribute