继承
原型链
prototype
是函数上的一个属性
__proto__
是对象实例上的属性,指向其构造函数的 prototype
属性
原型层层往上形成了原型链,需要注意的是
1 2 3 4 5 6 7 8 9
| Object.__proto__ === Function.prototype Function.__proto__ === Function.prototype (function (){}).__proto__ === Function.prototype Function.prototype.__proto__ === Object.prototype Object.prototype.__proto__ === null
(() => {}).__proto__ === Function.prototype (() => {}).prototype === undefined
|
ES6 class 相关的原型链相关知识
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class A {} A.__proto__ === Function.prototype A.prototype.__proto__ === Object.prototype
class B extends A{}
let a = new A() let b = new B()
B.__proto__ === A B.prototype.__proto__ === A.prototype
b.__proto__ === B.prototype b.__proto__.__proto__ === A.prototype b.__proto__.__proto__ === a.__proto__
Object.setPrototypeOf = function (obj, proto) { obj.__proto__ = proto; return obj; }
Object.setPrototypeOf(B.prototype, A.prototype);
Object.setPrototypeOf(B, A);
|
原型链继承
通过原型链实现继承
- 缺点
- 引用类型的属性绘本所有实例共享
- 创建
Child
实例无法向 Parent
传参
- 原型链
child.__proto__ -> Child.prototype -> new Parent()
Child.prototype.constructor -> Parent
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function Parent(){
} Parent.prototype.sayName = function(){ console.log(this.name) } function Child(name){ this.name = name } Child.prototype = new Parent()
const child = new Child('child')
child.sayName() console.log(child) console.log(child instanceof Parent) console.log(child instanceof Child) console.log(child.__proto__ === Child.prototype) console.log(Child.prototype.constructor === Parent)
|
借用构造函数继承
在子类中调用父类的构造函数绑定在子类的 this
上
- 优点
- 避免了引用类型被共享的问题
Child
可以向 Parent
传参
- 缺点
- 原型链
child.__proto__ -> Child.prototype
Child.prototype.constructor -> Child
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function Parent2(name){ this.name = name this.sayName = function(){ console.log(this.name) } } function Child2(name){ Parent2.call(this, name) }
var child2 = new Child2('child')
child2.sayName() console.log(child2) console.log(child2 instanceof Parent2) console.log(child2 instanceof Child2) console.log(child2.__proto__ === Child2.prototype) console.log(Child2.prototype.constructor === Child2)
|
组合继承
在子类中调用父类掉构造函数绑定到子类的 this
上,把子类的原型等于父类的实例
- 优点
- 缺点
- 原型链
child.__proto__ -> Child.prototype
Child.prototype.constructor -> Child
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function Parent3(name){ this.name = name } Parent3.prototype.sayName = function(){ console.log(this.name) } function Child3(name){ Parent3.call(this, name) } Child3.prototype = new Parent() Child3.prototype.constructor = Child3
const child3 = new Child3('child3')
child3.sayName() console.log(child3) console.log(child3 instanceof Parent2) console.log(child3 instanceof Child3) console.log(child3.__proto__ === Child3.prototype) console.log(Child3.prototype.constructor === Child3)
|
原型式继承
将传入的对象作为创建的对象的原型
- 缺点
- 原型链
child.__proto__ -> F.prototype -> o
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const P = { name: 'P', sayName(){ console.log(this.name) } } function CreateObj(o){ function F(){} F.prototype = o return new F() } const child4 = CreateObj(P)
child4.sayName() console.log(child4) console.log(child4 instanceof Object) console.log(child4.__proto__ === P)
|
寄生式继承
创建一个封装继承过程的函数,用来增强对象,然后返回对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const P = { name: 'P', sayName(){ console.log(this.name) } } function CreateObj1(o, name){ var clone = Object.create(o) clone.name = name return clone }
const child5 = CreateObj1(P, 'child5') child5.sayName() console.log(child5) console.log(child5 instanceof Object) console.log(child5.__proto__ === P)
|
寄生组合式继承
- 优点
- 只调用一次父类构造函数
- 避免在
Parent.prototype
创建不必要多余的属性
- 原型链保持不变,能正常使用
instanceof
和 isPrototypeOf
- 原型链
child.__proto__ -> Child.prototype
Child.prototype.constructor -> Child
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| function object(o){ function F(){} F.prototype = o return new F() }
function inherit(child, parent){ const prototype = object(parent.prototype) prototype.constructor = child child.prototype = prototype }
function Parent6(name){ this.name = name } Parent6.prototype.sayName = function(){ console.log(this.name) }
function Child6(name){ Parent6.call(this, name) }
inherit(Child6, Parent6)
const child6 = new Child6('child6')
child6.sayName() console.log(child6) console.log(child6 instanceof Child6) console.log(child6 instanceof Parent6) console.log(child6.__proto__ === Child6.prototype) console.log(Child6.prototype.constructor === Child6)
|
源码地址