You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

浏览器运行WebSocket类代码报错:无法读取未声明的私有成员#serverSocket

解决私有成员#serverSocket读取错误问题

问题描述

运行下述ControlPanel类代码时,在#monitorConnection()方法内触发错误:

Cannot read private member #serverSocket from an object whose class did not declare it

原代码:

class ControlPanel {
    #serverSocket;
    constructor() {
        this.#connectToWebSocketServer();
        this.#monitorConnection();
        console.log("ControlPanel::new");
    }
    #connectToWebSocketServer() {
        this.#serverSocket = new WebSocket(window.location.toString().startsWith('https')
          ? window.location.toString().replace("https", "wss")
          : window.location.toString().replace("http", "wss")
        );
        this.#serverSocket.onclose = this.#onWebSocketClose;
        this.#serverSocket.onerror = this.#onWebSocketError;
        this.#serverSocket.onmessage = this.#onWebSocketMessage;
        this.#serverSocket.onopen = this.#onWebSocketOpen;
        console.log("ControlPanel::#connectToWebSocketServer");
    }
    #monitorConnection() {
        setInterval(function() { if(this.#serverSocket.readyState != 1) this.#connectToWebSocketServer() }, 1500);
    }
    #onWebSocketClose(event) {
        console.debug("ControlPanel::#onWebSocketClose ", event);
    }
    #onWebSocketError(event) {
        console.debug("ControlPanel::#onWebSocketError ", event);
    }
    #onWebSocketMessage(event) {
        console.log("ControlPanel::#onWebSocketMessage ", event);
    }
    #onWebSocketOpen(event) {
        console.debug("ControlPanel::#onWebSocketOpen ", event);
    }
}
const controlPanel = new slim.generator.ControlPanel(); 

此外,将#onWebSocketOpen方法更新为以下代码后,WebSocket首次建立连接时也会触发相同错误:

#onWebSocketOpen(event) {
    console.debug("ControlPanel::#onWebSocketOpen ", event);
    this.#serverSocket.send();
}

问题根源

两处错误的核心都是**this指向不对**:

  • setInterval里用普通function当回调,此时this指向浏览器全局对象window,不是ControlPanel的实例,自然读不到类的私有成员#serverSocket
  • 给WebSocket绑定事件时,直接赋值this.#onWebSocketOpen这种函数引用,触发事件时this会指向WebSocket实例本身,同样不是ControlPanel实例,无法访问私有成员

修复方法

1. 修复定时器回调的this指向

把setInterval的普通函数改成箭头函数,箭头函数会继承外层作用域的this,也就是ControlPanel实例:

#monitorConnection() {
    setInterval(() => { 
        if(this.#serverSocket.readyState !== 1) this.#connectToWebSocketServer() 
    }, 1500);
}

2. 修复WebSocket事件的this指向

有两种常用方式:

方式一:用bind绑定实例this

在绑定事件时,给每个事件处理函数绑定当前实例的this:

#connectToWebSocketServer() {
    this.#serverSocket = new WebSocket(window.location.toString().startsWith('https')
      ? window.location.toString().replace("https", "wss")
      : window.location.toString().replace("http", "wss")
    );
    this.#serverSocket.onclose = this.#onWebSocketClose.bind(this);
    this.#serverSocket.onerror = this.#onWebSocketError.bind(this);
    this.#serverSocket.onmessage = this.#onWebSocketMessage.bind(this);
    this.#serverSocket.onopen = this.#onWebSocketOpen.bind(this);
    console.log("ControlPanel::#connectToWebSocketServer");
}

方式二:用箭头函数包裹事件处理函数

通过箭头函数间接调用原方法,确保this指向ControlPanel实例:

#connectToWebSocketServer() {
    this.#serverSocket = new WebSocket(window.location.toString().startsWith('https')
      ? window.location.toString().replace("https", "wss")
      : window.location.toString().replace("http", "wss")
    );
    this.#serverSocket.onclose = (event) => this.#onWebSocketClose(event);
    this.#serverSocket.onerror = (event) => this.#onWebSocketError(event);
    this.#serverSocket.onmessage = (event) => this.#onWebSocketMessage(event);
    this.#serverSocket.onopen = (event) => this.#onWebSocketOpen(event);
    console.log("ControlPanel::#connectToWebSocketServer");
}

做完以上修改后,两处场景的this都会正确指向ControlPanel实例,就能正常访问私有成员#serverSocket了。

内容的提问来源于stack exchange,提问作者Jeff Greer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 17:53:29