在这里须要注意的是,在JavaScript中并无类的概念,咱们的写法只是为了去模仿类,在JavaScript中类的实现是基于原型链、原型委托实现面向对象的。javascript
function P1() {
this.name = "p1"
}
P1.prototype.say = function() {
console.log('say')
}
function C1() {
P1.call(this) // 关键
this.age = 1
}
复制代码
这是最简单的一种方式,可是这种方式存在一种明显的缺陷,即只能继承构造函数内的属性,不能继承原型链上的属性和方法。java
function P2() {
this.name = 'p2'
this.arr = [1,2,3]
}
P2.prototype.say = function() {
console.log('say')
}
function C2() {
this.age = 2
}
C2.prototype = new P2()
let s1 = new C2()
let s2 = new C2()
复制代码
这是经过原型链的方式实现继承,咱们通过将子类(C2
)的prototype
属性挂载到父类(P2
)的实例对象(new P2()
)上,当访问访问子类实例没有的方法的时候,会访问子类的prototype
属性,若是子类的prototype
上也没有该方法,则会访问prototype
的__proto__
属性。造成的继承关系: s1.prototype === new P2()
,new P2().__proto__ === P2.prototype
app
这种方式的实现较第一种有明显的改进,可是也存在一些问题:因为全部实例共用prototype
属性,当咱们经过某个实例修改了原型链上的某个属性值的时候,其余的实例也会受到影响。这是违背面向对象的。函数
组合方式是将第一种方式和第二种方式结合起来,优化
function P3() {
this.name = "p3"
this.arr = [1,2,3]
}
P3.prototype.say = function() {
console.log('say')
}
function C3() {
P3.call(this)
this.age = 3
}
C3.prototype = P3.prototype
复制代码
咱们把父类的中的属性经过call写到子类中,而后经过子类实例化的每一个实例对象中都会有这个属性值,当改变其中一个实例中的属性的时候,其余的实例对象不会受到影响;而后将子类的prototype属性挂载到父类的prototype属性上,就能够访问父类原型上的方法。可是这种方法也存在一些问题,当咱们访问C3.prototype
的constructor属性的时候会发现是P3
,这可能会引发一些误解。这是由于咱们直接使C3.prototype = P3.prototype
,当咱们访问C3.prototype
的时候实际上是访问的是,P3.prototype
。这里咱们很容易想到重写C3.prototype
的constructor
属性。可是咱们必须引入一个中间的变量来表示C3.prototype
而后将中间变量的__proto__
指向父类。若是不引入中间变量当咱们修改的C3.prototype
的constructor
,由于C3.prototype、P3.prototype
指向同一个引用,P3.prototype
的constructor
属性也会被修改。ui
function P4() {
this.name = "p4"
this.arr = [1,2,3]
}
P4.prototype.say = function() {
console.log('say')
}
function C4() {
P4.call(this)
this.age = 4
}
C4.prototype = Obiect.create(P4.prototype)
C4.prototype.constructor = C4
复制代码
这是组合方式的优化方式,经过C4.prototype = Obiect.create(P4.prototype)
这段代码,将C4.prototype
的__proto__
属性指向P4.prototype
,当咱们修改了C4.prototype
上的constructor
属性·的时候,P4.prototype
的constructor
属性并不会受到影响。this
这里C4.prototype = Obiect.create(P4.prototype) 至关于下面这段代码:spa
function F() {}
F.prototype = P4.prototype
C4.prototype = new F()
复制代码
圣杯模式,yahoo 贡献的高端写法:YUI3库有个inherit,如今不用了,了解一下:prototype
let inherit = (function() {
let F = function(){}
return function(Child, Father) {
F.prototype = Father.prototype
Child.prototype = new F()
Child.prototype.constructor = Child
Child.prototype.uber = Father.prototype
}
})()
复制代码
这个方法只能继承父类的原型上的方法,不能继承构造函数内部的方法。code