了解一下JavaScript继承的方法

在这里须要注意的是,在JavaScript中并无类的概念,咱们的写法只是为了去模仿类,在JavaScript中类的实现是基于原型链、原型委托实现面向对象的。javascript

一、构造函数使用call、apply

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.prototypeapp

这种方式的实现较第一种有明显的改进,可是也存在一些问题:因为全部实例共用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.prototypeconstructor属性。可是咱们必须引入一个中间的变量来表示C3.prototype而后将中间变量的__proto__指向父类。若是不引入中间变量当咱们修改的C3.prototypeconstructor,由于C3.prototype、P3.prototype指向同一个引用,P3.prototypeconstructor属性也会被修改。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.prototypeconstructor属性并不会受到影响。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

相关文章
相关标签/搜索