class="markdown_views prism-atom-one-dark">
原型链继承
code
class="prism language-class ="tags" href="/tags/JS.html" title=js>js"> class="token keyword">function class="token function">Parent class="token punctuation">( class="token punctuation">) class="token punctuation">{
class="token keyword">this class="token punctuation">. cars class="token operator">= class="token punctuation">[ class="token string">'Lamborghini' class="token punctuation">, class="token string">'Maserati' class="token punctuation">, class="token string">'Bentley' class="token punctuation">] class="token punctuation">;
class="token punctuation">}
Parentclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototypeclass="token punctuation">. class="token function-variable function">showCars class="token operator">= class="token keyword">function class="token punctuation">( class="token punctuation">) class="token punctuation">{
class="token comment">// console.log(this.cars);
class="token punctuation">} class="token punctuation">;
class="token keyword">function class="token function">Child class="token punctuation">( class="token punctuation">) class="token punctuation">{ class="token punctuation">}
Childclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototype class="token operator">= class="token keyword">new class="token class -name">Parent class="token punctuation">( class="token punctuation">) class="token punctuation">;
class="token comment">// let parent = new Parent()
class="token comment">// parent.cars.push('QQ')
class="token comment">// console.log(parent.cars);
class="token keyword">var child1 class="token operator">= class="token keyword">new class="token class -name">Child class="token punctuation">( class="token punctuation">) class="token punctuation">;
child1class="token punctuation">. carsclass="token punctuation">. class="token function">push class="token punctuation">( class="token string">'QQ' class="token punctuation">)
consoleclass="token punctuation">. class="token function">log class="token punctuation">( child1class="token punctuation">. carsclass="token punctuation">) class="token punctuation">;
class="token keyword">var child2 class="token operator">= class="token keyword">new class="token class -name">Child class="token punctuation">( class="token punctuation">) class="token punctuation">;
consoleclass="token punctuation">. class="token function">log class="token punctuation">( child2class="token punctuation">. carsclass="token punctuation">) class="token punctuation">;
consoleclass="token punctuation">. class="token function">log class="token punctuation">( Childclass="token punctuation">. __proto__ class="token operator">== Objectclass="token punctuation">. __proto__class="token punctuation">) class="token punctuation">;
思路 将子构造函数的原型指向父构造函数的一个实例 总结 优点 :可以通过 instanceof 和 isPrototypeOf 的检测 缺点 : 1.子构造函数实例化对象时 不能传参, 2.子实例化对象共享父构造函数的属性(比如cars),一旦改变,其他都改变 子实例化对象相互影响
借用构造函数继承(经典继承)
code
class="prism language-class ="tags" href="/tags/JS.html" title=js>js"> class="token keyword">function class="token function">Parent class="token punctuation">( nameclass="token punctuation">) class="token punctuation">{
class="token keyword">this class="token punctuation">. cars class="token operator">= class="token punctuation">[ class="token string">'Lamborghini' class="token punctuation">, class="token string">'Maserati' class="token punctuation">, class="token string">'Bentley' class="token punctuation">] class="token punctuation">;
class="token keyword">this class="token punctuation">. name class="token operator">= name
class="token punctuation">}
Parentclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototypeclass="token punctuation">. class="token function-variable function">showCars class="token operator">= class="token keyword">function class="token punctuation">( class="token punctuation">) class="token punctuation">{
consoleclass="token punctuation">. class="token function">log class="token punctuation">( class="token keyword">this class="token punctuation">. nameclass="token punctuation">) class="token punctuation">;
class="token punctuation">} class="token punctuation">;
class="token keyword">function class="token function">Child class="token punctuation">( class="token operator">... argsclass="token punctuation">) class="token punctuation">{
Parentclass="token punctuation">. class="token function">call class="token punctuation">( class="token keyword">this class="token punctuation">, argsclass="token punctuation">) class="token comment">//子构造函数里 借用父构造函数
class="token punctuation">}
class="token keyword">let child1 class="token operator">= class="token keyword">new class="token class -name">Child class="token punctuation">( class="token string">'one' class="token punctuation">)
child1class="token punctuation">. class="token function">showCars class="token punctuation">( class="token punctuation">)
consoleclass="token punctuation">. class="token function">log class="token punctuation">( child1class="token punctuation">) class="token punctuation">;
class="token keyword">let child2 class="token operator">= class="token keyword">new class="token class -name">Child class="token punctuation">( class="token string">'two' class="token punctuation">)
child2class="token punctuation">. class="token function">showCars class="token punctuation">( class="token punctuation">)
consoleclass="token punctuation">. class="token function">log class="token punctuation">( child2class="token punctuation">. nameclass="token punctuation">) class="token punctuation">;
思路:在子构造函数内部调用父构造函数 总结 优点 : 1.可以向子构造函数传递参数 2.子实例化对象相互不影响 缺点 :方法在函数中定义,无法调用父构造函数的方法 注意:父构造函数并没有与子构造函数 建立联系 所以,子实例化对象的原型身上并没有 showCars 方法
组合继承
code
class="prism language-class ="tags" href="/tags/JS.html" title=js>js">class="token keyword">function class="token function">Parent class="token punctuation">( nameclass="token punctuation">, ageclass="token punctuation">) class="token punctuation">{
class="token keyword">this class="token punctuation">. name class="token operator">= nameclass="token punctuation">;
class="token keyword">this class="token punctuation">. age class="token operator">= ageclass="token punctuation">;
class="token keyword">this class="token punctuation">. uselessclass="token operator">= class="token string">'empty'
class="token punctuation">}
Parentclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototypeclass="token punctuation">. class="token function-variable function">show class="token operator">= class="token keyword">function class="token punctuation">( class="token punctuation">) class="token punctuation">{
class="token comment">// console.log(this.name + this.age);
consoleclass="token punctuation">. class="token function">log class="token punctuation">( class="token string">"Parent show" class="token punctuation">) class="token punctuation">;
class="token punctuation">} class="token punctuation">;
class="token comment">// let parent = new Parent('parent','40')
class="token comment">// for (const key in parent) {
class="token comment">// console.log(key);
class="token comment">// }
class="token keyword">function class="token function">Child class="token punctuation">( class="token operator">... argsclass="token punctuation">) class="token punctuation">{
Parentclass="token punctuation">. class="token function">apply class="token punctuation">( class="token keyword">this class="token punctuation">, argsclass="token punctuation">) class="token punctuation">; class="token comment">//借用构造函数 实现传参
class="token punctuation">}
Childclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototype class="token operator">= class="token keyword">new class="token class -name">Parent class="token punctuation">( class="token punctuation">) class="token punctuation">; class="token comment">// 原型链继承 实现调用父构造身上的方法
class="token comment">// 这里要将子构造函数的构造器指回 Child
class="token comment">// 否则,子构造函数上没有constructor方法,根据原型链向上找到父构造函数的constructor,
class="token comment">// 最终指向了父构造函数
class="token comment">// 子构造函数原型方法还可能被覆盖掉
Childclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototypeclass="token punctuation">. constructor class="token operator">= Childclass="token punctuation">;
class="token comment">// console.log(Child.class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototype.constructor);
Childclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototypeclass="token punctuation">. class="token function-variable function">show class="token operator">= class="token keyword">function class="token punctuation">( class="token punctuation">) class="token punctuation">{
consoleclass="token punctuation">. class="token function">log class="token punctuation">( class="token string">"child show" class="token punctuation">) class="token punctuation">;
class="token punctuation">} class="token punctuation">;
consoleclass="token punctuation">. class="token function">log class="token punctuation">( class="token keyword">new class="token class -name">Parent class="token punctuation">( class="token punctuation">) class="token punctuation">) class="token punctuation">;
class="token keyword">let child class="token operator">= class="token keyword">new class="token class -name">Child class="token punctuation">( class="token string">"kk" class="token punctuation">, class="token string">"18" class="token punctuation">) class="token punctuation">;
class="token comment">// child.show()
class="token keyword">let child2 class="token operator">= class="token keyword">new class="token class -name">Child class="token punctuation">( class="token string">"lele" class="token punctuation">, class="token string">"13" class="token punctuation">) class="token punctuation">;
class="token comment">// child2.show()
consoleclass="token punctuation">. class="token function">log class="token punctuation">( child2class="token punctuation">) class="token punctuation">;
class="token keyword">for class="token punctuation">( class="token keyword">const key class="token keyword">in child2class="token punctuation">) class="token punctuation">{
consoleclass="token punctuation">. class="token function">log class="token punctuation">( keyclass="token punctuation">) class="token punctuation">;
class="token punctuation">}
思路: 结合原型链继承实现调用父构造函数的方法 利用借用构造函数实现传参定义属性 总结 组合继承:结合了原型链继承和构造函数继承 **优点:**同时可以传递参数,共享父构造函数方法,而且有自己的方法 缺点: 1.两次调用了父构造函数,浪费内存 2.constructor 可以被 in 遍历出来
原型式继承
code
class="prism language-class ="tags" href="/tags/JS.html" title=js>js">class="token keyword">function class="token function">Parent class="token punctuation">( class="token punctuation">) class="token punctuation">{
class="token keyword">this class="token punctuation">. cars class="token operator">= class="token punctuation">[ class="token string">'Lamborghini' class="token punctuation">, class="token string">'Maserati' class="token punctuation">, class="token string">'Bentley' class="token punctuation">]
class="token punctuation">}
Parentclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototypeclass="token punctuation">. class="token function-variable function">show class="token operator">= class="token keyword">function class="token punctuation">( class="token punctuation">) class="token punctuation">{
consoleclass="token punctuation">. class="token function">log class="token punctuation">( class="token keyword">this class="token punctuation">. carsclass="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token keyword">let parent class="token operator">= class="token keyword">new class="token class -name">Parent class="token punctuation">( class="token punctuation">)
class="token keyword">function class="token function">object class="token punctuation">( objclass="token punctuation">) class="token punctuation">{
class="token keyword">function class="token function">Fn class="token punctuation">( class="token punctuation">) class="token punctuation">{ class="token punctuation">}
Fnclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototype class="token operator">= obj
class="token keyword">return class="token keyword">new class="token class -name">Fn class="token punctuation">( class="token punctuation">)
class="token punctuation">}
class="token keyword">let obj class="token operator">= class="token function">object class="token punctuation">( parentclass="token punctuation">)
consoleclass="token punctuation">. class="token function">log class="token punctuation">( objclass="token punctuation">) class="token punctuation">;
class="token comment">// 原型式继承
class="token comment">// 不需要父构造函数,根据父构造函数的实例化对象,模拟一个对象
2.总结 根据父构造函数的实例化对象,模拟一个对象 优点 不需要知道父构造函数 缺点 只是赋值了一个对象出来,无法传参
寄生继承
code
class="prism language-class ="tags" href="/tags/JS.html" title=js>js"> class="token keyword">let parentclass="token operator">= class="token punctuation">{
nameclass="token punctuation">: class="token string">'parent' class="token punctuation">,
ageclass="token punctuation">: class="token string">'18'
class="token punctuation">}
class="token keyword">function class="token function">object class="token punctuation">( objclass="token punctuation">) class="token punctuation">{ class="token comment">//这里手动实现了Object.create()
class="token keyword">function class="token function">Fn class="token punctuation">( class="token punctuation">) class="token punctuation">{ class="token punctuation">}
Fnclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototype class="token operator">= obj
class="token keyword">return class="token keyword">new class="token class -name">Fn class="token punctuation">( class="token punctuation">)
class="token punctuation">}
class="token keyword">function class="token function">create class="token punctuation">( objclass="token punctuation">) class="token punctuation">{ class="token comment">//
class="token keyword">let clone class="token operator">= class="token function">object class="token punctuation">( objclass="token punctuation">)
cloneclass="token punctuation">. class="token function-variable function">have class="token operator">= class="token keyword">function class="token punctuation">( class="token punctuation">) class="token punctuation">{
consoleclass="token punctuation">. class="token function">log class="token punctuation">( class="token string">'clone have car' class="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token keyword">return clone
class="token punctuation">}
class="token keyword">let child class="token operator">= class="token function">create class="token punctuation">( parentclass="token punctuation">)
consoleclass="token punctuation">. class="token function">log class="token punctuation">( childclass="token punctuation">. nameclass="token punctuation">) class="token punctuation">;
consoleclass="token punctuation">. class="token function">log class="token punctuation">( childclass="token punctuation">. ageclass="token punctuation">) class="token punctuation">;
childclass="token punctuation">. class="token function">have class="token punctuation">( class="token punctuation">)
总结 寄生继承 优点 :根据对象克隆一个具有相同属性和方法的对象,而且可以具有自己的方法 缺点 :无法被复用,无法传参
寄生组合继承
code
class="prism language-class ="tags" href="/tags/JS.html" title=js>js">class="token keyword">function class="token function">extend class="token punctuation">( supclass="token punctuation">, subclass="token punctuation">) class="token punctuation">{
subclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototype class="token operator">= Objectclass="token punctuation">. class="token function">create class="token punctuation">( supclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototypeclass="token punctuation">) class="token comment">// 重置子构造函数的原型
Objectclass="token punctuation">. class="token function">defineProperty class="token punctuation">( subclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototypeclass="token punctuation">, class="token string">'constructor' class="token punctuation">, class="token punctuation">{ class="token comment">//修正原型链
valueclass="token punctuation">: subclass="token punctuation">,
enumerableclass="token punctuation">: class="token boolean">false
class="token punctuation">} class="token punctuation">)
class="token punctuation">}
class="token keyword">function class="token function">Parent class="token punctuation">( nameclass="token punctuation">, ageclass="token punctuation">) class="token punctuation">{
class="token keyword">this class="token punctuation">. name class="token operator">= name
class="token keyword">this class="token punctuation">. age class="token operator">= age
class="token punctuation">}
Parentclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototypeclass="token punctuation">. class="token function-variable function">show class="token operator">= class="token keyword">function class="token punctuation">( class="token punctuation">) class="token punctuation">{
consoleclass="token punctuation">. class="token function">log class="token punctuation">( class="token keyword">this class="token punctuation">. nameclass="token operator">+ class="token string">':' class="token operator">+ class="token keyword">this class="token punctuation">. ageclass="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token keyword">let parent class="token operator">= class="token keyword">new class="token class -name">Parent class="token punctuation">( class="token string">'parent' class="token punctuation">, class="token number">18 class="token punctuation">)
consoleclass="token punctuation">. class="token function">dir class="token punctuation">( parentclass="token punctuation">) class="token punctuation">;
class="token keyword">function class="token function">Child class="token punctuation">( class="token operator">... argsclass="token punctuation">) class="token punctuation">{
Parentclass="token punctuation">. class="token function">apply class="token punctuation">( class="token keyword">this class="token punctuation">, argsclass="token punctuation">) class="token comment">//借用构造函数,并实现传参
class="token punctuation">}
class="token function">extend class="token punctuation">( Parentclass="token punctuation">, Childclass="token punctuation">) class="token comment">//实现继承
Childclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototypeclass="token punctuation">. class="token function-variable function">show class="token operator">= class="token keyword">function class="token punctuation">( class="token punctuation">) class="token punctuation">{ class="token comment">// 子构造函数 覆盖父构造函数的show方法
consoleclass="token punctuation">. class="token function">log class="token punctuation">( class="token string">'Child show' class="token punctuation">) class="token punctuation">;
class="token punctuation">}
Childclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototypeclass="token punctuation">. class="token function-variable function">getName class="token operator">= class="token keyword">function class="token punctuation">( class="token punctuation">) class="token punctuation">{ class="token comment">// 子构造函数 可以有自己的方法
consoleclass="token punctuation">. class="token function">log class="token punctuation">( class="token keyword">this class="token punctuation">. nameclass="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token keyword">let child class="token operator">= class="token keyword">new class="token class -name">Child class="token punctuation">( class="token string">'kk' class="token punctuation">, class="token number">18 class="token punctuation">)
consoleclass="token punctuation">. class="token function">dir class="token punctuation">( childclass="token punctuation">) class="token punctuation">;
childclass="token punctuation">. class="token function">getName class="token punctuation">( class="token punctuation">)
consoleclass="token punctuation">. class="token function">log class="token punctuation">( Childclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototypeclass="token punctuation">. __proto__ class="token operator">== Parentclass="token punctuation">. class ="tags" href="/tags/PROTOTYPE.html" title=prototype>prototypeclass="token punctuation">) class="token punctuation">;
consoleclass="token punctuation">. class="token function">log class="token punctuation">( Childclass="token punctuation">. __proto__ class="token operator">== Objectclass="token punctuation">. __proto__class="token punctuation">) class="token punctuation">;
总结 class 之前是最完备的继承方式
class="prism language-class ="tags" href="/tags/JS.html" title=js>js">class="token keyword">class class="token class -name">User class="token punctuation">{
class="token function">constructor class="token punctuation">( nameclass="token punctuation">) class="token punctuation">{
class="token keyword">this class="token punctuation">. name class="token operator">= name
class="token keyword">this class="token punctuation">. cars class="token operator">= class="token punctuation">[ class="token string">'Lamborghini' class="token punctuation">, class="token string">'Maserati' class="token punctuation">, class="token string">'Bentley' class="token punctuation">]
class="token punctuation">}
class="token function">getCars class="token punctuation">( class="token punctuation">) class="token punctuation">{
consoleclass="token punctuation">. class="token function">log class="token punctuation">( class="token keyword">this class="token punctuation">. carsclass="token punctuation">) class="token punctuation">;
class="token punctuation">}
class="token punctuation">}
class="token keyword">class class="token class -name">Admin class="token keyword">extends class="token class -name">User class="token punctuation">{
class="token function">constructor class="token punctuation">( nameclass="token punctuation">, ageclass="token punctuation">) class="token punctuation">{
class="token keyword">super class="token punctuation">( nameclass="token punctuation">)
class="token keyword">this class="token punctuation">. age class="token operator">= age
class="token punctuation">}
class="token punctuation">}
class="token keyword">let admin class="token operator">= class="token keyword">new class="token class -name">Admin class="token punctuation">( class="token string">'admin' class="token punctuation">, class="token number">18 class="token punctuation">)
adminclass="token punctuation">. class="token function">getCars class="token punctuation">( class="token punctuation">)
consoleclass="token punctuation">. class="token function">log class="token punctuation">( adminclass="token punctuation">. ageclass="token punctuation">) class="token punctuation">;
class="token comment">/*
总结:完美
*/