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

如何通过WebSocket传递自定义类对象并调用其方法?

问题原因与解决方案

核心原因

JSON.stringify()只能序列化对象的可枚举自有属性,类的方法(比如add())是挂载在类的原型链上的,不会被序列化。当客户端解析JSON后得到的只是一个普通JavaScript对象,和Digit类没有原型链关联,自然找不到add()方法。

解决方法

方法1:客户端重建类实例

在客户端也定义完全相同的Digit类,将服务端传来的普通对象的属性赋值给新的类实例:

服务端代码:

// 直接序列化实例的自有属性即可
WS.send(JSON.stringify(C));

客户端代码:

// 客户端必须定义和服务端一致的Digit类
class Digit {
  constructor(data) {
    // 把服务端传来的属性赋值给当前实例
    Object.assign(this, data);
  }
  add() {
    // 实现和服务端相同的方法逻辑
  }
}

// 接收消息并处理
ws.onmessage = function(event) {
  const rawData = JSON.parse(event.data);
  // 用普通对象重建Digit实例
  const C = new Digit(rawData);
  // 现在可以正常调用add()
  C.add();
};

方法2:添加类标识,客户端按需重建

在服务端序列化时给对象添加一个类类型标记,客户端根据标记判断并重建对应类的实例:

服务端代码:

// 给序列化对象添加类型标识
const serializedData = JSON.stringify({
  __type__: 'Digit',
  ...C // 展开实例的所有自有属性
});
WS.send(serializedData);

客户端代码:

class Digit {
  constructor(data) {
    Object.assign(this, data);
  }
  add() { /* 方法逻辑 */ }
}

ws.onmessage = function(event) {
  const obj = JSON.parse(event.data);
  let instance;
  // 根据类型标识判断并重建实例
  if (obj.__type__ === 'Digit') {
    delete obj.__type__; // 移除类型标记,避免污染实例
    instance = new Digit(obj);
  }
  instance.add(); // 正常调用方法
};

方法3:自定义类的序列化逻辑

在Digit类中定义toJSON()方法,主动控制序列化的内容,避免手动拼接:

服务端代码:

class Digit {
  constructor(value) {
    this.value = value; // 假设实例有这个业务属性
  }
  add() { /* 方法逻辑 */ }
  // 自定义序列化规则
  toJSON() {
    return {
      __type__: 'Digit',
      value: this.value
    };
  }
}

// 直接序列化实例即可
WS.send(JSON.stringify(new Digit(10)));

客户端处理逻辑和方法2一致,根据__type__标记重建实例即可。

注意事项

  • 客户端必须保持Digit类的定义和服务端一致(包括方法逻辑),可以把类抽成公共JS文件,让服务端和客户端共用,避免重复代码。
  • 不要尝试直接序列化类的方法:JSON不支持函数类型的序列化,强行转换会把函数变成字符串,无法直接调用,同时也存在安全风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 03:45:42