当对象从服务器发送到客户端时,JS原型方法消失了

JS prototype method disappears when object is sent to client from server

本文关键字:JS 原型 消失了 方法 客户端 对象 服务器      更新时间:2023-09-26

我正在使用节点服务器将一些对象发送到我的前端代码。我使用原型向对象添加了一些方法,但是当我将它们发送到前端时,原型方法消失了。对象仍具有具有原型方法名称的属性,但该值已设置为未定义。有没有办法在客户端恢复原型方法?

我的代码如下所示:

服务器.js

function Class (data) {
  this.value = data;
}
Class.prototype.isEven = function() {
  return this.value % 2 === 0;
};
app.get('/data', function(req, res) {
  db.query('select * from table', function(err, rows, fields) {
    var items = [];
    for (var i = 0; i < rows.length; i++) {
      items.push(
        new Class(rows[i]['value'])
      );
    }
    res.send(items);
  });
});

客户端.js

$.ajax({url: "/data", type: "GET", success: function(data) {
  var item = data[0];
  console.log(item.isEven); // displays 'undefined'
});

对象通过jQuery Ajax以JSON(纯文本格式)的形式发送。 JSON 将序列化对象上的对象属性,但是当它转换回另一端的对象时,它将被转换为纯 JS 对象,而不是任何特定类型的对象,因此它不会有任何自定义原型。

JSON 格式没有用于捕获对象类型从而保留原型方法的内置机制。 因此,当您将 JSON 解析回另一端的对象时,您不会获得原型。

此外,JSON 从不序列化函数/方法,只序列化数据。

对于像您这样的情况,通常的解决方法是只发送一个纯值数组。 接收端知道它将接收一个普通的值数组。 如果它希望该值数组位于Class对象中,那么它将采用该数组并构造一个使用适当数据初始化的Class对象数组。

$.ajax({url: "/data", type: "GET", success: function(data) {
  // convert array of plain objects into array of Class objects
  var items = data.map(function(item) {
      return new Class(item.value);
  });
  console.log(items[0].isEven());
});

更好的方法是将服务器代码更改为仅发送一个普通的数据值数组,而不是一个对象数组,因为它只是不必要的开销。

这是因为Javascript在字符串化类对象时不考虑原型属性。

如果你做了JSON.stringify(new Class(2))你会看到{"value":2}

为此,您应该提供 toJSON 方法,该方法在字符串化对象时调用,如下所示:

Class.prototype.toJSON = function() {
    return {
        value: this.value,
        isEven: this.isEven
    }
}

但是,如果您这样做,您将看到该功能尚未显示。为什么?这是因为函数不能字符串化为 JSON,因为 JSON 中不存在函数。

函数不仅仅是它们的代码,正如你在这个答案中看到的。

要解决此问题,您可以简单地获取函数的值,执行以下操作:

Class.prototype.toJSON = function() {
    return {
        value: this.value,
        isEven: this.isEven.toString()
    }
}