js继承in-ES6-ES5

ES5 与 ES6 继承写法对比,底层都回到原型链。

#type / concept #status / growing #resource / javascript #resource / ecmascript

[!info] related notes

ES5 继承 vs ES6 class extends

一句话定义

ES5 通过原型链 + call/apply 借用构造函数实现继承;ES6 用 class extends + super 提供语法糖,底层机制完全相同——都是原型链连接。

核心机制 / 工作原理

ES5 方式一:原型链继承

function Animal(name) {
  this.name = name;
}
Animal.prototype.speak = function () {
  return this.name + ' makes a noise.';
};

function Dog(name) {
  Animal.call(this, name); // 借用父构造函数,继承实例属性
}
Dog.prototype = Object.create(Animal.prototype); // 原型链连接
Dog.prototype.constructor = Dog; // 修复 constructor 指向
Dog.prototype.bark = function () {
  return this.name + ' barks!';
};

关键步骤:

  1. Animal.call(this, name) — 借用构造函数,把父类实例属性复制到子类实例
  2. Object.create(Animal.prototype) — 创建以父原型为原型的新对象,建立原型链
  3. 修复 constructor 指向

ES5 方式二:组合继承(最常用)

上面的写法就是组合继承 = 借用构造函数 + 原型链。解决了:

  • 借用构造函数只能继承实例属性,不能继承原型方法
  • 原型链继承时,引用类型的属性会被所有实例共享

ES6 class extends

class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    return this.name + ' makes a noise.';
  }
}

class Dog extends Animal {
  constructor(name) {
    super(name); // 必须先调用 super,才能使用 this
  }
  bark() {
    return this.name + ' barks!';
  }
}

class 是语法糖

ES6 的 class 完全等价于 ES5 的原型链写法:

  • class 中的方法定义在 Constructor.prototype
  • super() 等价于 Animal.call(this, name)
  • extends 等价于 Dog.prototype = Object.create(Animal.prototype)
  • 静态方法定义在 Constructor 自身上

最小例子

// ES5
function Shape(color) {
  this.color = color;
}
Shape.prototype.describe = function () {
  return 'A ' + this.color + ' shape';
};

function Circle(color, radius) {
  Shape.call(this, color);
  this.radius = radius;
}
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;
Circle.prototype.area = function () {
  return Math.PI * this.radius ** 2;
};

// ES6 —— 同样的效果
class Shape {
  constructor(color) { this.color = color; }
  describe() { return 'A ' + this.color + ' shape'; }
}
class Circle extends Shape {
  constructor(color, radius) {
    super(color);
    this.radius = radius;
  }
  area() { return Math.PI * this.radius ** 2; }
}

边界与常见误解

  • “ES6 class 是新的继承机制” — 不是。class 是原型链的语法糖,底层没有变化。instanceof 和原型链遍历完全一致。
  • “super 是调用父类”super() 调用父构造函数;super.method() 调用父原型上的方法。两者不同。
  • 忘记调用 super — 在子类 constructor 中,必须先调用 super() 才能使用 this,否则 ReferenceError。
  • ES5 原型链继承的坑 — 如果不 Object.create 而直接 Dog.prototype = new Animal(),会在原型对象上执行构造函数,产生副作用。
  • __proto__ vs prototype — 子类 __proto__ 指向父类(静态方法继承),子类 prototype.__proto__ 指向父类 prototype(实例方法继承)。
创建于 2026/3/15 更新于 2026/5/27