Prototype and inheritance

brief introduction

Six concepts of object-oriented: object (instance), class, encapsulation, inheritance, polymorphism and aggregation.

js does not have the concept of class. It extends new objects based on objects (constructors and prototype objects).  

Encapsulation: put the independent attributes in the constructor and the shared part on the prototype. Save memory and keep the instance object independent.

Constructor: the constructor is the same as ordinary functions. The difference is that it gets an object by executing new, and returns this by default, which points to the newly created object.

Create an object through the constructor:

function Person (name) {
    this.name = name;
}
Person.prototype.sayName = function () {
    alert(this.name)
}
var p1 = new Person('Tom', 10);
//p1:'Tom',10;__proto__: sayName

The following relationships exist:

p1.__proto__ === Person.prototype // true
Person.prototype.constructor === Person //true
p1.constructor === Person.prototype.constructor //true

 

Three important attributes

_proto_

Object unique. Point to the prototype of the corresponding constructor, that is, the prototype attribute.

Function: when accessing the properties of an object, the object itself (private property) will be searched. If not, it will be searched in its_ proto_ The prototype object pointed to by the property cannot be found until object Protoytpe object, which returns undefined before it is. (prototype chain lookup)

The prototype chain is simply through_ proto_ A chain that connects objects to null.

p1----->Person.prototype----->Object.prototype----->null

Everything in js is an Object and can be based on_ proto_ Prototype chain found Object Protoytpe prototypes are all instances (objects) of the built-in class Object.

 

prototype

Function unique. Refers to the prototype object of the function.

Role: contains attributes and methods shared by instances (public attributes or methods).

Object.prototype.__proto__ === null  // true

 

constructor

Object unique. Refers to the constructor of the object. The default built-in property in the prototype object points to the constructor itself.

 

Built in (class) object constructor

Number / String / Boolean / Object/ Array / Date / Funtion / RegExp / Error

console.log(Person.__proto__ === Function.prototype);//true
console.log(Number.__proto__ === Function.prototype);//true
console.log(String.__proto__ === Function.prototype);//true
console.log(Boolean.__proto__ === Function.prototype);//true
console.log(Date.__proto__ === Function.prototype);//true
console.log(Array.__proto__ === Function.prototype);//true
console.log(Error.__proto__ === Function.prototype);//true
console.log(RegExp.__proto__ === Function.prototype);//true

 

Detection example

p1 instanceof Person
// true
Person.prototype.isPrototypeOf(p1)
// true
p1.hasOwnProperty('name')
// true
p1.hasOwnProperty('sayName')
// false

Instance instanceof class

Check whether the instance belongs to a class. As long as the prototype of the class appears on the prototype chain of the instance object, it returns true. It is applicable to array or regular, but not to basic data types

isPrototypeOf

Detect the relationship between a proptype object and an instance

Object Hasownproperty

Check whether a property is the private property of the instance object. If it is not the property of the object or the private property, false will be returned

Attribute in object

Regardless of public or private attributes, as long as it is the attribute of the object, it returns true

attr in obj && ! attr. Hasownproperty (attr) is a property of an object and is not private

 

inherit

Construction inheritance: execute the constructor of the parent class in the constructor of the child class and point to its own this

        function Parent(name){
            this.name = name
        }
        Parent.prototype.getName = function(){
            return this.name
        }
        function Child (){
            Parent.call(this,'hello')
        }
        var child = new Child()
        console.log(child.name)  // hello   
        console.log(child.getName())  // child.getName is not a function
  

Disadvantages:

Methods and properties on the parent class prototype cannot be inherited. Only properties and methods of the parent class instance can be inherited.

 

Prototype inheritance: take the instance of the parent class as the prototype of the child class

        function Parent(){
            this.name = 'hello'
            this.hobbies = ['walking','music']
        }
        Parent.prototype.getName = function(){
            return this.name
        }
        function Child (){

        }
        // Let child prototype. Constructor points to Parent
        Child.prototype = new Parent()
        Child.prototype.constructor = Child
        var child1 = new Child()
        var child2 = new Child()
        console.log(child1.name)  // hello
        console.log(child1.getName())  // hello
        child2.hobbies[0] = 'baseketball'
        console.log(child2.hobbies)  // ["baseketball", "music"]
        console.log(child1.hobbies)  // ["baseketball", "music"]
        

Disadvantages: multiple instances point to the same prototype. Modifying one of them will affect others (including reference type values); You cannot pass parameters to a parent class.

 

Composite inheritance: a combination of prototype inheritance and construction inheritance

        function Parent(name){
            this.name = name
            this.hobbies = ['walking', 'music']
        }
        Parent.prototype.getName = function(){
            return this.name
        }
        function Child (name){
            Parent.call(this, name)
        }
        // Let child prototype. Constructor points to Parent
        Child.prototype = new Parent()
        Child.prototype.constructor = Child
        var child1 = new Child('hello')
        var child2 = new Child()
        console.log(child1.name)  // hello
        console.log(child1.getName())  // hello
        
        child2.hobbies[0] = 'baseketball'
        console.log(child2.hobbies)  // ["baseketball", "music"]
        console.log(child1.hobbies)  // ["walking", "music"]

 

Parasitic composite inheritance: it avoids the defect of instantiating the parent class every time in composite inheritance

       function Parent(name){
            this.name = name
            this.hobbies = ['walking', 'music']
        }
        Parent.prototype.getName = function(){
            return this.name
        }
        function Child (name){
            Parent.call(this, name)
        }
        // Change new Parent to parent prototype
        // Child.prototype = Parent.prototype
        // Shallow copy
        Child.prototype = Object.create(Parent.prototype)
        Child.prototype.constructor = Child
        var child1 = new Child('hello')
        var child2 = new Child()
        console.log(child1.name)  // hello
        console.log(child1.getName())  // hello

        child2.hobbies[0] = 'baseketball'
        console.log(child2.hobbies)  // ["baseketball", "music"]
        console.log(child1.hobbies)  // ["walking", "music"]

Disadvantages: when changing the prototype prototype, we should pay attention to the interaction between the prototype objects of the subclass and the parent class, which can be avoided by shallow copy

 

ES6 class inheritance

It is implemented directly through extensions, and super is used to call the constructor of the parent class in the subclass. The definition of class includes the constructor constructor and the function getName() defined on the prototype object.

        class Parent{
            constructor(name){
                this.name = name
            }
            getName() {
                return this.name
            }

        }
        class child extends Parent{
            constructor(name){
                super(name)   //Call the constructor of the parent class with super
            }
        }
        var child1 = new Parent('hello')
        console.log(child1.name) // hello

 

Add

Keywords: Javascript

Added by colake on Thu, 27 Jan 2022 22:59:55 +0200