我使用节点服务器将一些对象发送到我的前端代码。我使用原型为我的对象添加了一些方法,但是当我将它们发送到前端时,原型方法就消失了。对象仍然具有原型方法名称的属性,但该值已设置为undefined。有没有办法可以在客户端恢复原型方法?
我的代码如下所示:
server.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);
});
});
client.js
$.ajax({url: "/data", type: "GET", success: function(data) {
var item = data[0];
console.log(item.isEven); // displays 'undefined'
});
答案 0 :(得分:3)
对象通过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());
});
更好的办法是将服务器代码更改为只发送一个简单的数据值数组,而不是一个对象数组,因为它只是不必要的开销。
答案 1 :(得分:1)
这是因为在字符串化类对象时,Javascript不会考虑原型属性。
如果您JSON.stringify(new Class(2))
{"value":2}
,则会看到toJSON
。
为此,您应该提供Class.prototype.toJSON = function() {
return {
value: this.value,
isEven: this.isEven
}
}
方法,该方法在对字符串进行字符串化时调用,如下所示:
Class.prototype.toJSON = function() {
return {
value: this.value,
isEven: this.isEven.toString()
}
}
但是如果你这样做,你会发现该功能还没有显示出来。为什么?这是因为函数不能被字母化为JSON,因为JSON中不存在函数。
您可以在this answer中看到函数远远超过其代码。
要解决这个问题,您只需获取函数的值即可:
public void DrawLetter() {
new AsyncTask<Void, Void, Bitmap>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Bitmap doInBackground(Void... params) {
Draw();
Draw2();
return currentBitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if(bitmap!=null) {
loadImageToImageView();
}
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}