需要解释错误消息“TypeError:接收者必须是类的实例”

use*_*860 4 javascript oop inheritance typeerror ecmascript-next

当我运行这段代码时:

'use strict';

class Base {
  constructor() {
    this._public();
  }
}

class Child extends Base {
  constructor() {
    super();
  }

  _public() {
    this.#privateMethod();
  }

  #privateMethod() {
    this.bar = 1234;
  }
}

const c = new Child();
console.log(c.bar);
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

   this.#privateMethod();
         ^

TypeError: Receiver must be an instance of class Child
Run Code Online (Sandbox Code Playgroud)

据我了解 JavaScript,以下代码中的接收者正是 Child 类的一个实例。它甚至显示在开发工具检查器中:

开发工具截图

那么有人可以向我解释一下发生了什么事吗?这是一个错误还是什么?


实际上FF显示了更准确的错误信息:

Uncaught TypeError: can't access private field or method: object is not the right class
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 5

这是为什么最好不要从构造函数调用公共实例方法的一个示例。当您的Base类构造函数调用时this._public()Child的初始化尚未完成。最早可以使用Child会员是在返回之后,而不是之前。 super()只有在super()返回之后Child,自动初始化(例如设置私有字段和方法,以及初始化通过类字段语法定义的公共属性)才完成。您也可以在公共类字段中看到这一点:

class Base {
    constructor() {
        console.log("test" in this); // false
    }
}

class Child extends Base {
    test; // <== Public class field
    
    constructor() {
        super();
        console.log("test" in this); // true
    }
}

new Child();
Run Code Online (Sandbox Code Playgroud)

您可以在返回后立即this._public()Child的构造函数调用super()(尽管,最好不要从构造函数调用公共方法!最好#privateMethod直接调用),因为Child到那时就已经完全准备好了(除了您正在执行的任何初始化之外)当然,在它的构造函数中),但不是在返回之前 super()