Uncaught TypeError: 无法设置私有字段:对象不是正确的类问题求助
这个问题我之前也踩过坑,核心原因是私有方法#tick的上下文(this指向)丢失了,我来给你一步步拆解:
错误根源
当你在startTimer里执行setInterval(this.#tick, this.#timeBetweenTicks)时,你只是把#tick方法本身作为参数传给了setInterval,并没有带上它的上下文。setInterval在执行回调时,默认会把this绑定到全局的Window对象(非严格模式下)。
而JavaScript的私有字段(比如#currentTime)是严格绑定到所属类的实例的——只有CyclingTimer的实例才能访问这些私有成员。Window对象显然不是CyclingTimer的实例,所以当#tick里尝试访问this.#currentTime时,就会抛出你看到的错误,这也和你调试时看到#tick里的this是Window对象完全吻合。
而startTimer里的this是正常的,因为你是通过CyclingTimer实例调用startTimer方法的,此时this自然指向实例本身。
解决方法
有三种常用的方式可以修复这个问题,核心都是让#tick执行时的this指向CyclingTimer实例:
方法1:用箭头函数包裹回调
箭头函数会继承外层作用域的this,这里就是CyclingTimer实例:
startTimer() { // 此处调试打印this时输出CyclingTimer对象,符合预期 setInterval(() => this.#tick(), this.#timeBetweenTicks); }
方法2:用bind绑定this
通过bind方法手动把#tick的this绑定到实例:
startTimer() { // 此处调试打印this时输出CyclingTimer对象,符合预期 setInterval(this.#tick.bind(this), this.#timeBetweenTicks); }
方法3:在构造函数里提前绑定
如果这个方法会被多次使用,可以在构造函数里一次性绑定好this:
constructor(maximumTime, timeBetweenTicks) { super(); this.#maximumTime = maximumTime; this.#timeBetweenTicks = timeBetweenTicks; this.#currentTime = 1; // 提前绑定this,后续调用#tick时都会指向当前实例 this.#tick = this.#tick.bind(this); } startTimer() { setInterval(this.#tick, this.#timeBetweenTicks); }
额外说明
JavaScript的私有成员(#开头的字段/方法)有严格的访问限制,不仅外部无法访问,即使是继承的子类也不能直接访问父类的私有成员。所以确保this指向正确的类实例,是访问私有成员的前提。
内容的提问来源于stack exchange,提问作者Blank

