← 返回题目列表

ES6 class 中 super 和 new.target 分别有什么作用?

中等 第 21 / 28 题 更新于 2026/07/29
ES6classsuper

简化版

super 用于在子类中调用父类构造函数或父类方法。派生类构造函数里必须先调用 super(),才能使用 this

new.target 表示当前构造调用实际使用的构造函数,可用于判断函数是否通过 new 调用,也可用于实现抽象基类限制。

详细版

class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    return `${this.name} makes noise`;
  }
}

class Dog extends Animal {
  constructor(name) {
    super(name);
  }

  speak() {
    return super.speak() + " and barks";
  }
}

new.target

class Base {
  constructor() {
    if (new.target === Base) {
      throw new Error("Base cannot be constructed directly");
    }
  }
}

完整版教学

一、super 的两个位置

super 在构造函数里表示调用父类构造函数。

在方法里,super.method() 表示调用父类原型上的方法。

位置含义
constructor调用父类构造函数
实例方法查找父类原型方法
静态方法查找父类静态方法
constructor -> super(...)
method      -> super.method(...)

super 不是一个普通变量,它和类的继承关系、方法的内部槽绑定在一起。

二、派生类为什么要先 super

派生类自己的 this 需要由父类构造过程初始化。

class Child extends Parent {
  constructor() {
    super();
    this.ready = true;
  }
}

如果在 super() 前访问 this,会抛错。

class Bad extends Parent {
  constructor() {
    this.x = 1; // ReferenceError
    super();
  }
}

三、super.method 的 this 仍是当前对象

class Parent {
  say() {
    return this.name;
  }
}

class Child extends Parent {
  say() {
    return super.say();
  }
}

const child = new Child();
child.name = "Ada";
console.log(child.say()); // Ada

super.say() 找的是父类方法,但调用时的 this 仍然是当前实例。

四、静态方法里也能使用 super

class Parent {
  static version() {
    return 1;
  }
}

class Child extends Parent {
  static version() {
    return super.version() + 1;
  }
}

静态上下文中的 super 指向父类构造函数本身,而不是父类原型。

五、new.target 判断真实构造目标

function User() {
  console.log(new.target === User);
}

User(); // false 或 undefined 语义
new User(); // true

在类构造函数里,new.target 表示最终被 new 的类。

class Base {
  constructor() {
    console.log(new.target.name);
  }
}

class Child extends Base {}
new Child(); // Child

六、抽象基类限制

JavaScript 没有原生抽象类关键字,但可以用 new.target 做运行时限制。

class Shape {
  constructor() {
    if (new.target === Shape) {
      throw new Error("abstract");
    }
  }
}

这不是类型系统约束,而是运行时保护。

七、常见误区与追问

  • 误区:super.method 里的 this 是父类实例。 实际 this 通常仍是当前子类实例。
  • 误区:子类构造函数可以先用 this 再 super。 派生类必须先调用 super()
  • 误区:super 是父类对象的普通引用。 它依赖方法定义位置和内部继承绑定。
  • 误区:new.target 只在 class 里能用。 普通函数中也能使用。
  • 追问:静态方法中的 super 指向哪里? 指向父类构造函数,用于访问父类静态成员。
  • 追问:new.target 能实现什么限制? 可阻止基类被直接实例化,模拟抽象类。

八、加强记忆

记忆图:

Child instance
  ├─ this -> current instance
  ├─ super() -> Parent constructor
  └─ super.method() -> Parent.prototype.method with current this

回答时抓三点:派生构造函数先 super()super.method 找父类但 this 仍是当前对象,new.target 表示真实构造目标。