代码之家  ›  专栏  ›  技术社区  ›  d.k

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

  •  2
  • d.k  · 技术社区  · 1 年前

    当我运行此代码时:

    '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);
    

    我得到以下错误:

       this.#privateMethod();
             ^
    
    TypeError: Receiver must be an instance of class Child
    

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

    dev-tools screenshot

    有人能向我解释一下发生了什么事吗?是虫子还是什么?


    实际上,FF显示了一个更准确的错误消息:

    Uncaught TypeError: can't access private field or method: object is not the right class
    
    1 回复  |  直到 1 年前
        1
  •  4
  •   T.J. Crowder    1 年前

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

    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();

    你可以打电话 这个_public() 从…起 小孩 的构造函数 super() return(不过,再次强调,最好不要从构造函数中调用公共方法!最好调用 #privateMethod 直接),因为 小孩 届时将完全准备就绪(当然,除了您在其构造函数中进行的任何初始化),但不是 之前 super() 返回。