JS继承总结(小白友好篇)

529 阅读3分钟

继承的本质: 子类继承父类的属性和方法。(目的是让子类的实例可以调取父类的属性和方法。)

ES5中的继承

  • 原型继承
    • 原理: 让父类中的属性和方法在子类实例的原型链上

      CHILD.prototype = new PARENT()

      CHILD.prototype.constrctor = CHILD

    • 特点:

      • 不像其他语言一样的继承(其他语言的继承是拷贝继承,会把父类的属性和方法拷贝到子类中,供子类调取使用),它是把父类的实例放在子类实例的原型链上,实例想调取这些方法,是基于__proro__原型链查找机制完成的。
      • 子类可以重写父类上的方法,会导致父类其他的实例也会收到影响。
      • 父类中私有或者公有的属性方法,最后都会变成子类中公有方法。
// 原型链继承举🌰
// 父类
function Parent(x) {
    this.x = x
} 
Parent.prototye.getX = function() {
    console.log(this.x)
}
// 子类
function Child(y) {
    this.y = y
}
// 继承
Child.prototype = new Parent('y') // 子类的原型指向父类的实例
Child.prototype.constrctor = Child // 保证子类构造函数的完整性
Child.prototype.getY = function() {
    console.log(this.y)
}
const child = new Child('x')
child.y // y 成功访问子类属性
child.x // x 成功访问父类属性
child.getX() // x 成功调用父类方法
child.getY() // y 成功调用子类本身方法

// 子类可以通过 CHILD.prototype.__proto__修改父类,并对父类的其他实例造成影响
Child.prototype.__proto__.other = function () {
    console.log('other')
}
const parent = new Parent(200)
parent.other() // other
  • CALL继承
    • 原理:
      • 在CHILD方法中把PARENT方法当作普通函数来执行,让PARENT中的this指向CHILD的实例,相当于给CHILD实例是设置了很多私有的属性和方法
    • 特点:
      • 只能继承父类私有的属性和方法(因为是把PARENT当作普通函数执行,和其原型上的属性和方法没有关系)
      • 父类私有变为子类私有
// CALL继承举🌰
// 父类
function Parent(x) {
    this.x = x
    this.thisGetX = function () {
        console.log(this.x)
    }
}
Parent.prototype.getX = function () {
    console.log(this.x)
}
// 子类
function Child(y) {
    // this => Child的实例
    Parent.call(this, 200)
    this.y = y
}
Child.prototype.getY = function () {
    console.log(this.y)
}

const child = new Child(100)
console.log(child.x) // 成功访问父类属性
child.getX() // 报错 无法访问父类原型链上的属性和方法
  • 寄生组合继承
    • 原理: CALL继承+类似原型继承
    • 特点:
      • 父类私有和公有的属性、方法,分别是子类实例的共同和私有方法(推荐)
// 寄生组合继承举🌰
// 父类
function Parent(x) {
    this.x = x
    this.thisGetX = function () {
        console.log(this.x)
    }
}
Parent.prototype.getX = function () {
    console.log(this.x)
}

// 子类
function Child(y) {
    // this => Child的实例
    Parent.call(this, 200)
    this.y = y
}

// Object.create  => 创建一个空对象,让空对象__proto__指向 Parent.prototype
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
const child = new Child(100)
console.log(child.x) // 成功访问父类属性
child.getX() // 200

// 实现object.create方法
function create(obj) {
    function Fn()
  Fn.prototype = obj
  return new Fn()
}

ES6中的继承

  • class
    • 原理: class CHILD extends Parent {} => CHILD.prototype._ proto_ = PARENT.prototype
    • 特点:
      • 子类继承父类可以不屑constructor,一旦写了,constructor内的第一句话必须是super(), super() 的作用类似call继承。
// 父类
// ES6中基于class创造出来的类不能当作普通函数执行、不允许重定向原型的指向
class Parent {
    constructor(x) {
        this.x = x
    }
    getX() {
        console.log(this.x)
    }
}
// 子类
// class Child {
//  constructor(y) {
//      this.y = y
//  }
//  getY() {
//      console.log(this.y)
//  }
// }
// ES6中的继承 
class Child extends Parent {
    constructor(y) {
        super(200)
        this.y = y
    }
    getY() {
        console.log(this.y)
    }
}
const child = new Child(100)
console.log(child.x) // 成功访问父类属性
child.getX() //  成功调用父类方法