<>js Prototype chain in ,6 The way of inheritance and its cases

We know how to face people (OOP) The three characteristics of : inherit , encapsulation , polymorphic ( heavy load , rewrite )

js It's not strictly object-oriented language , because js Object oriented is based on prototype chain .

<> Prototype chain

The prototype chain is composed of __proto__ A chain like structure connected in series . Every function has one prototype attribute , There are also __proto__, Each object has only one
__proto__ attribute ; In general, we put the attribute method constructor in the , Put the method in the prototype below , Object's
__proto__ That points to the constructor prototype, The end point of the prototype chain is Object.prototype, Up again Object.prototype.__proto__=null

1. Instance has no concrete constructor
let obj={} console.log(obj.__proto__== Object.prototype) //true console.log(
Object.prototype.__proto__) //null
2. The constructor of an instance is a custom constructor
function Persion(){}// Constructor let p=new Persion()// example console.log(p.__proto__==
Persion.prototype) //true console.log(Persion.prototype.__proto__==Object.
prototype) //true console.log(Object.prototype.__proto__) //null
3. The constructor of an instance is a built-in constructor
let p = new Array() console.log(p.__proto__ == Array.prototype) //true console.
log(Array.__proto__ ==Function.prototype)//true console.log(Function.__proto__
== Function.prototype)//true ,Function Is a constructor , It's also an object console.log(Function.prototype
.__proto__==Object.prototype)//true console.log(Object.prototype.__proto__)
//null

Function The constructor of a constructor is itself ,Function Access as instantiated object Function Constructors are available , therefore Function.__proto__ Can be accessed Function.prototype; Any function inherits Function All methods and properties of , and Function Is a built-in constructor , It's also an object , It's all inheritance Object All properties and methods of ,Function.prototype.__proto__=Object.prototype

First write one here Persion Superclass , This class has a property called name, There is an example method introduce, There is a prototype approach hobby
function Parent(name){ this.name=name this.introduce=function(){ console.log(
"my name is"+this.name) } } Parent.prototype.hobby=function(hobby){ console.log(
this.name+" like "+hobby) }
<>1. Prototype chain inheritance

The prototype of a subclass points to an instance of the parent class ( Subclass .prototype=new Superclass ())
function Child() {} // Subclass // Child.prototype.sleep=function(){ //
console.log(this.name+"is sleeping") // }1 Child.prototype = new Parent("yzh")
// In order not to destroy the prototype chain , take Male Of constructor Point to itself Child.prototype.constructor=Child Child.
prototype.sleep=function(){ console.log(this.name+" is sleeping") }//2 Parent.
prototype.eat=function(){ console.log(this.name+" is eating") } var child=new
Child() console.log(Child) child.introduce() child.hobby(" sing ") child.sleep()
child.eat() console.log(child instanceof Parent) //true console.log(child
instanceof Child) //true
notes : If Male Prototype method sleep Put in 1 Position , Will report a mistake child.sleep is not a function, Put in 2 position , output yzh is
sleeping

The characteristics of this method of inheritance :

* The relationship between the subclass and the parent class is directional , An instance is an instance of a subclass , It is also an instance of the parent class
* Prototype method or property added by parent class , All subclasses can be accessed
* Easy to use
shortcoming :

* If you want to add a property or method to a subclass , Only in new Parent()
after , It cannot be placed in a constructor , Code example above , If the new method is placed before changing the direction of the subclass prototype , After changing the direction, the new method will be useless , Subclass prototype Already pointed to the parent class
*
All instances of subclass , Share all parent properties , Subclasses cannot have their own properties , If there are multiple instances , One of the instances modified the value of the parent reference type , Then all instances will change , For example, I just want to take an example of eat The method is changed to “is
eating apple”, The method will change in all instances
* You can't inherit more , Because it changed the direction of the prototype chain , Cannot point to more than one parent class , Therefore, it can only be inherited by itself
* When creating a subclass , Cannot pass a parameter to a parent constructor , Because after changing the direction of the prototype chain of the subclass , The properties and methods of the subclass are invalid
<>2. Constructive inheritance (call,apply inherit )

hold All properties and methods of the parent object , Copy into child object
function Child(name){ Parent.call(this,name) } var child=new Child("yzh")
console.log(child.name) //yzh child.introduce() child.hobby("sing") console.log(
childinstanceof Parent) //false console.log(child instanceof Child) //true
advantage :

* It solves the problem that the subclasses in the prototype chain inheritance share the parent class attribute
* The created subclass instance can pass parameters to the parent class
* Multiple inheritance can be realized ,call Changing the parent class's this
shortcoming :

* An instance is an instance of a subclass , The parent class of is not
* Only instance properties and methods of the parent class can be inherited , Methods on a parent prototype cannot be inherited
*
Function reuse is not possible , Each subclass has a copy of the properties and methods of the parent function , When child call Parent On the method ,Parent Internal this It's pointing to child,Parent Internal this The properties and methods on are copied to child above , If every instance of a subclass copies the properties and methods of the parent class , It takes up a lot of memory , And when the method of the parent class changes , A subclass instance that has already been created cannot update methods , Because the original parent method has been copied as its own method .
<>3. Combinatorial inheritance ( Prototype chain inheritance and construction inheritance )
function Child(name) { Parent.call(this,name) // Constructive inheritance , Call the parent class the second time } // Prototype chain inheritance Child.
prototype=new Parent() Child.prototype.constructor=Child var child=new Child(
"yzh") // Instances of subclasses pass parameters to the parent class , Calling the parent class for the first time console.log(child.name) child.introduce() child.
hobby("sing") console.log(child instanceof Parent) //true console.log(child
instanceof Child) //true
advantage : It combines the advantages of prototype chain inheritance and construction inheritance

* Subclass can pass parameters to parent class
* An instance is an instance of a subclass , It is also an instance of the parent class
* There is no common parent class reference property between multiple instances
* Instances can inherit the properties and methods of the parent instance , You can also inherit properties and methods from prototypes
shortcoming : This method calls the constructor of the parent class twice , Two instances are generated , The same properties exist in both instances and prototypes

<>4. Copy inheritance
function Child(name){ var parent = new Parent(name); for(var key in parent){
Child.prototype[key] = parent[key]; } } var child=new Child("yzh") console.log(
child.name) //yzh child.introduce() child.hobby("sing") console.log(child
instanceof Parent) //false console.log(child instanceof Child) //true
advantage :

* Support multiple inheritance
shortcoming :

* Cannot get method of parent class that cannot be enumerated , This method uses for in To traverse Parent Properties in , For example, multi box checked attribute , This is the property that cannot be enumerated
* It's inefficient , High memory consumption
<>5. Parasitic combinatorial inheritance

Parasitic combinatorial inheritance : Inheriting properties by borrowing constructors , Methods are inherited through a hybrid form of the prototype chain .

thinking : It is not necessary to call the constructor of the parent class in order to specify the prototype of the subclass , All we need is a copy of the parent prototype . Essentially , It is to use parasitic inheritance to inherit the prototype of the parent class , Then assign the result to the prototype of the subclass

In fact, it does not need to instantiate the parent class constructor , You can also get the properties and methods of the parent class , It is to directly instantiate a copy of a temporary parent class , Implement prototype chain inheritance
function Child(name) { Parent.call(this,name) // Constructive inheritance } (function(){ // Create a temporary class
var Temp=function(){} Temp.prototype=Parent.prototype // The prototype of a subclass points to an instance of the parent class
Child.prototype=new Temp() })() var p=new Child("yzh") console.log(p.name)//yzh
p.hobby("sing")//yzh like sing p.introduce()//my name is yzh
advantage : Combine all the advantages of composite inheritance , This method is perfect

<>6.ES6 inherit
class Parent{ constructor(name){ this.name=name } introduce(){ console.log("my
name is " + this.name) } hobby(hobby){ console.log(this.name + " like " + hobby)
} } class Child extends Parent{ constructor(name,age){ super(name)
// Constructive inheritance , Inheritable Parent Property on constructor this.age=age } } var p = new Child("yzh") p.introduce(
) //my name is yzh p.hobby("apple")//yzh like apple console.log(p instanceof
Parent) // true console.log(p instanceof Child) //true
We use it es6 The method of writing makes the object more clear , It's more like object-oriented programming ; It is used in this method extends and super
Two keywords , In subclass constructor Call in method super method , Used to inherit the parent class this object

<> Prototype drag
<style type="text/css"> *{ margin: 0; padding: 0; } body,html{ width: 100%;
height: 100%; } .box{ width: 100px; height: 100px; background-color:
palevioletred; position: absolute; color: #fff; display: flex; justify-content:
center; align-items: center; padding: 10px; } </style> <div class="box" id="box"
>box1 Unlimited scope </div> <div class="box" id="box2">box2 Limited scope </div> // Drag without limits class
Drag{ constructor(ele){ this.box=document.querySelector(ele) this.addHandler() }
addHandler(){ this.box.onmousedown=(e)=>{ let _x=e.offsetX // The distance from the upper boundary of the distance element when the mouse is pressed let
_y=e.offsetY e.preventDefault() // Sliding and lifting events are bound to document upper document.onmousemove=(e)=>
{ let _left=e.clientX-_x //e.clientX The distance of the mouse from the top of the browser let _top=e.clientY-_y //
console.log(_left,_top) // Distance from document this.move(_left,_top) } document.onmouseup=()
=>{ document.onmousemove=null } } } move(_left,_top){ this.box.style.left=_left+
'px' this.box.style.top=_top+'px' } } // Limited scope inherit Drag class limitDrag extends Drag
{ constructor(ele) { super(ele) } // rewrite move function move(_left,_top){ if(_left<0)_left=
0 if(_top<0)_top=0 if(_left>document.body.offsetWidth-this.box.offsetWidth)
_left=document.body.offsetWidth-this.box.offsetWidth if(_top>document.body.
offsetHeight-this.box.offsetHeight) _top=document.body.offsetHeight-this.box.
offsetHeightthis.box.style.left=_left+'px' this.box.style.top=_top+'px' } } new
Drag('#box') new limitDrag('#box2')

Technology