ES6的`class`中,`super`关键字在构造函数和非构造函数中的行为有何不同?

发布于:2025-04-17 ⋅ 阅读:(27) ⋅ 点赞:(0)

在 ES6 的 class 中,super 关键字的行为在 构造函数非构造函数(普通方法) 中有显著区别,主要体现在以下方面:


1. 构造函数中的 super

行为规则
  1. 必须显式调用
    在子类的构造函数中,必须先调用 super(),才能使用 this。否则会抛出错误:

    class Child extends Parent {
      constructor() {
        this.name = "Alice"; // ❌ 错误:Must call super constructor in derived class
        super();
      }
    }
    
  2. super 作为函数调用
    super() 的作用是调用父类的构造函数,并初始化子类实例的 this

    • 参数需传递给父类构造函数。
    • 相当于 Parent.prototype.constructor.call(this, ...args)
  3. 调用顺序
    super() 必须位于构造函数的最顶部(在访问 this 之前)。

示例
class Parent {
  constructor(name) {
    this.name = name;
  }
}

class Child extends Parent {
  constructor(name, age) {
    super(name); // ✅ 必须先调用 super()
    this.age = age;
  }
}

const child = new Child("Alice", 10);
console.log(child.name); // "Alice"
console.log(child.age);  // 10

2. 非构造函数中的 super(普通方法)

行为规则
  1. super 作为对象使用
    在普通方法中,super 指向 父类原型(Parent.prototype),用于调用父类方法。

    • super.method() 等价于 Parent.prototype.method.call(this)
  2. 可调用父类原型方法
    通过 super 可以访问父类原型上定义的方法,但无法直接访问父类实例属性。

  3. 无需强制调用顺序
    可以在方法内任意位置使用 super,无需在访问 this 之前调用。

示例
class Parent {
  sayHello() {
    console.log("Hello from Parent");
  }
}

class Child extends Parent {
  sayHello() {
    super.sayHello(); // ✅ 调用父类方法
    console.log("Hello from Child");
  }
}

const child = new Child();
child.sayHello(); 
// 输出:
// "Hello from Parent"
// "Hello from Child"

关键区别总结

特性 构造函数中的 super 非构造函数中的 super
调用形式 必须作为函数调用(super() 作为对象调用(super.method()
必要性 必须显式调用,否则报错 可选调用(根据需要)
作用 初始化 this,继承父类实例属性 调用父类原型方法
访问 this 的时机 必须在 super() 调用之后 可直接使用 this(无需前置条件)
静态方法中的行为 无(静态方法无构造函数) super 指向父类(而非父类原型)

静态方法中的 super

在静态方法中,super 指向 父类本身,而非父类原型:

class Parent {
  static staticMethod() {
    console.log("Parent static method");
  }
}

class Child extends Parent {
  static staticMethod() {
    super.staticMethod(); // 调用父类的静态方法
    console.log("Child static method");
  }
}

Child.staticMethod(); 
// 输出:
// "Parent static method"
// "Child static method"

常见错误场景

1. 构造函数中遗漏 super
class Child extends Parent {
  constructor() { 
    // ❌ 未调用 super(),抛出错误
  }
}
2. 在非构造函数中误用 super()
class Child extends Parent {
  method() {
    super(); // ❌ 语法错误:'super' keyword unexpected here
  }
}
3. 错误访问父类实例属性
class Parent {
  constructor() {
    this.value = 42;
  }
}

class Child extends Parent {
  getValue() {
    return super.value; // ❌ 无法通过 super 访问父类实例属性(返回 undefined)
  }
}

const child = new Child();
console.log(child.getValue()); // undefined

总结

  • 构造函数中的 super
    强制调用,用于初始化 this,确保父类实例属性正确继承。
  • 非构造函数中的 super
    用于调用父类原型方法,无需强制顺序,但需注意 super 的指向。
  • 静态方法中的 super
    指向父类本身,用于调用父类静态方法。

网站公告

今日签到

点亮在社区的每一天
去签到