人人都会AI编程

继承、super 关键字、私有属性

更新时间:2026-07-11

ES6 的 class 语法不仅提供了更贴近传统面向对象语言的类定义方式,还带来了清晰的继承机制和成员访问控制能力。下面分别讲解继承的实现、super 关键字的作用,以及如何定义和使用私有属性。


继承:使用 extends 构建类层级

类的继承通过 extends 关键字实现,底层依然是基于原型链的委托,只是语法更简洁、语义更明确。

class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    console.log(`${this.name} 发出声音`);
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name);          // 调用父类构造函数
    this.breed = breed;
  }
  speak() {
    console.log(`${this.name} 汪汪叫`);
  }
}

const d = new Dog('旺财', '金毛');
d.speak();                // 旺财 汪汪叫
  • extends 建立了两个原型链关系:Dog.prototype.proto === Animal.prototype(实例方法继承),以及 Dog.proto === Animal(静态方法继承)。
  • 子类可以覆盖(重写)父类的方法,实现多态;也可以通过 super 调用父类版本(见下文)。
  • 如果不显式定义 constructor,引擎会自动生成一个默认构造函数,并调用 super(...args) 将参数传递给父类。

super 关键字:连接父类的桥梁

super 在继承体系中有两个主要用途:

  1. 在子类构造函数中调用父类构造函数

super(...) 必须在使用 this 之前调用,否则会报错。这是因为 ES6 的类先创建父类实例,再由子类构造函数去修改它。

  1. 在子类方法中访问父类方法

无论是普通方法还是静态方法,都可以用 super.methodName() 调用父类的对应方法。

class Cat extends Animal {
  speak() {
    super.speak(); // 调用父类的 speak 方法
    console.log('喵喵~');
  }
}

const c = new Cat('小花');
c.speak();
// 小花 发出声音
// 喵喵~
  • super 在静态方法中同样可用,指向父类的静态方法。
  • 注意:super 不能像一个独立变量一样被单独引用或赋值,它只能在方法内部使用。

私有属性:安全的内部状态

ES2022 正式引入了私有属性私有方法,使用 # 前缀定义。这些成员只能被类内部访问,外部直接访问或继承的子类都无法获取。

class Counter {
  #count = 0;                // 私有实例属性
  #reset() {                 // 私有方法
    this.#count = 0;
  }

  increment() {
    this.#count++;
  }

  get value() {
    return this.#count;
  }

  doReset() {
    this.#reset();           // 内部可调用私有方法
  }
}

const c = new Counter();
c.increment();
console.log(c.value);         // 1
console.log(c.#count);        // SyntaxError(语法错误)

关键规则:

  • 私有属性必须在类顶层显式声明(例如 #count = 0),不能在构造函数中动态添加。
  • 子类完全无法访问父类的私有属性,即使使用 super 也不行。
  • 私有方法(如 #reset)同样只能在类内部调用。

私有属性补上了 JavaScript 类长久以来缺失的“封装”能力,让开发者能够保护内部状态不被意外修改,也不再依赖于 _ 前缀约定或 WeakMap 等 hack 方式。


小结

  • extends 让继承关系一目了然,原型链自动连通。
  • super 是调用父类方法和构造函数的标准方式,必须在访问 this 前使用。
  • # 私有成员提供了真正的封装,外部代码无法闯入,适用于需要严格保护的状态。

掌握了这三者,你已经能够用 class 写出结构清晰、职责明确、封装良好的面向对象代码。