js 中继承是怎么实现的

111 阅读1分钟

  • 使用构造函数实现继承

function Parent (){
    this.name='parent'
}
function Child(){
    Parent.call(this)
    this.sex='男'
}

以上便可以实现继承基类,但是通过构造函数实现的继承不能继承基类的原型链上的属性,比如不能继承下面的say方法

Parent.prototype.say=function(){
    
}
  • 使用原型链实现继承

function Parent (){
    this.name='parent'
}
function Child(){
    this.sex='男'
}
Child.prototype=new Parent()

以上便可以实现继承基类,但是通过原型链实现的继承所有实例会共用基类中的引用属性,如下 如果父类中添加number属性,在info1中操作number属性 在info2中也会同时改变

function Parent (){
    this.name='parent'
    this.number=[1,2,3]
}
var info1=new Child()
var info2=new Child()
info1.number.push(4)

  • 使用组合方式(原型链,构造函数)实现继承

function Parent (){
     this.name='parent'
     this.number=[1,2,3]
}
function Child(){
     Parent.call(this)
     this.sex='男'
}
Child.prototype=new Parent()//会重复执行父类构造函数,可以进行优化
//Child.prototype=Parent.prototype//不会重复执行父类构造函数
var info1=new Child()
var info2=new Child()
info1.number.push(4)

使用组合方式实现继承的方式不能解决 当前实例是否属于基类还是属于子类的问题,还需要以下优化

function Parent (){
     this.name='parent'
     this.number=[1,2,3]
}
function Child(){
     Parent.call(this)
     this.sex='男'
}

Child.prototype=Object.create(Parent.prototype)  //通过中间实例分割两个之间的引用 避免引起关联
Child.prototype.constructor=Child//可以通过此属性判断当前实例是否属于基类还是属于子类的问题
var info1=new Child()
var info2=new Child()
info1.number.push(4)
console.log(info1.constructor)
  • ES6的extends继承
class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y); // 调用父类的constructor(x, y)
    this.color = color;
  }

  toString() {
    return this.color + ' ' + super.toString(); // 调用父类的toString()
  }
}