ES6中类继承的实现

122 阅读2分钟

ES6中的class 类

我们深入一下它是如何实现的

我们来看mdn上的一个代码片段

//shape-父类
function Shape() {
    this.x = 0;
    this.y = 0;
}

Shape.prototype.move = function (x, y) {
    this.x += x;
    this.y += y;
    console.log(`Shape moved. x:${x},y:${y}`)
}

//Retangle子类
function Rectangle() {
    // 调用父类构造函数以初始化 x 和 y 属性
    // 会执行 Shape 构造函数,并将当前 Rectangle 实例(即 this)作为 Shape 构造函数的作用域。这意味着 Shape 构造函数中的 this.x = 0; 和 this.y = 0; 语句实际上是在设置 Rectangle 实例上的 x 和 y 属性,因此每个 Rectangle 实例都会拥有这些属性,并且它们会被初始化为 0
    // 确保了如果 Shape 构造函数中有任何其他初始化逻辑(例如订阅事件、设置默认值等),这些逻辑也会应用于 Rectangle 实例。
    Shape.call(this)//事实上,去掉这行代码Rectangle依旧可以得到x,y
}

//子类继承父类
Rectangle.prototype = Object.create(Shape.prototype,{
        constructor: {
            value: Rectangle,
            enumberable: false,
            writable: true,
            configurable: true
        }
    }
)
const rect = new Rectangle();

console.log("rect 是 Rectangle 类的实例吗?", rect instanceof Rectangle); // true
console.log("rect 是 Shape 类的实例吗?", rect instanceof Shape); // true
rect.move(1, 1); // 打印 'Shape moved.'
console.log(Object.getPrototypeOf(rect).constructor)

let shape1 = new Shape()
console.log("Shape.prototype:", Shape.prototype)
console.log("shape1的原型:", Object.getPrototypeOf("shape1:", shape1))
console.log("shape1.move:", shape1.move)//shape-父类
function Shape (){
    this.x = 0;
    this.y = 0;
}

Shape.prototype.move = function(x,y){
    this.x += x;
    this.y += y;
    console.log(`Shape moved. x:${x},y:${y}`)
}
let shape1 = new Shape()
shape1.move(3,2)
console.log("Shape.prototype:",Shape.prototype)
console.log("shape1的原型:",Object.getPrototypeOf("shape1:",shape1))
console.log("shape1.move:",shape1.move)
//Retangle子类
function Rectangle (){
    Shape.call(this)
}

//子类继承父类
Rectangle.prototype = Object.create(Shape.prototype,{
    constructor:{
        value:Rectangle,
        enumberable:false,
        writable:true,
        configurable:true
    }
})
const rect = new Rectangle();

console.log("rect 是 Rectangle 类的实例吗?", rect instanceof Rectangle); // true
console.log("rect 是 Shape 类的实例吗?", rect instanceof Shape); // true
rect.move(1, 1); // 打印 'Shape moved.'


打印结果如下

我们来画图理解

以下是等效的ES6版本

// 父类
class Shape {
  constructor() {
    this.x = 0;
    this.y = 0;
  }

  // 父类方法
  move(x, y) {
    this.x += x;
    this.y += y;
    console.info("Shape moved.");
  }
}

// 子类
class Rectangle extends Shape {
  constructor() {
    super(); // 调用父类构造函数。
  }
}

const rect = new Rectangle();

console.log("rect 是 Rectangle 类的实例吗?", rect instanceof Rectangle); // true
console.log("rect 是 Shape 类的实例吗?", rect instanceof Shape); // true
rect.move(1, 1); // 打印 'Shape moved.'

即改变子类对象的原型指向,同时手动将原型对象的constructor指向子类函数(如果不手动修改,则指向父类函数)