如果我在 Javascript 中有一个类声明,方法如下:
class Foo {
constructor(a, b) {
this.a = a;
this.b = b;
}
sum() {
return this.a + this.b;
}
}
然后我可以创建一个对象并调用它的
sum()
方法。
var bar = new Foo(2, 5); // {"a": 2, "b": 5}
var total = bar.sum(); // 7
我还可以将这个对象 (
bar
) 存储在数据库或本地存储中,方法是先将其转换为字符串:
localStorage.savedBar = JSON.stringify(bar); // "{\"a\": 2, \"b\": 5}"
但是,当我检索它时,我无法再访问它的方法。
var retrievedBar = JSON.parse(localStorage.savedBar); // {"a": 2, "b": 5}
var secondTotal = retrievedBar.sum(); // retrievedBar.sum is not a function!
这真的很烦人,因为这意味着我将不得不重建任何类对象。不得不说,
var goodRetrievedBar = new Foo(retrievedBar.a, retrievedBar.b);
var goodSecondTotal = goodRetrievedBar.sum(); // 7
对于这种情况来说这似乎很好,但是一旦我想到更深层嵌套的数据结构,我很快就会进入
for
循环和复杂逻辑的领域,以完成看似简单的任务。另外,如果我以后想改变我的班级:
class Foo {
constructor(a, b, c) {
this.a = a;
this.b = b;
if (typeof c !== 'undefined') {
this.c = c;
}
}
sum() {
if (this.c) {
return this.a + this.b + this.c;
}
return this.a + this.b;
}
}
我还必须更新我的解析代码以支持附加属性,
c
,当我对类所做的更改不需要我对代码进行任何其他更改时。
有没有更简单的方法来强制一个对象以某种方式将自己同化到一个类中?以简单有效的方式处理此问题的标准方法是什么?
函数通常不能在所有情况下进行序列化和反序列化(由于闭包),具有内部原型的对象(
Object.prototype
除外)也不能在反序列化后反映这些原型。
你可以做的是序列化实例自身的属性,然后在反序列化时,使用
Object.create
使得新实例的内部原型是类原型。
class Foo {
constructor(a, b, c) {
this.a = a;
this.b = b;
if (typeof c !== 'undefined') {
this.c = c;
}
}
sum() {
if (this.c) {
return this.a + this.b + this.c;
}
return this.a + this.b;
}
}
const f = new Foo(1, 2, 3);
const stringified = JSON.stringify(f);
const retrievedInstance = Object.create(Foo.prototype);
Object.assign(retrievedInstance, JSON.parse(stringified));
console.log(retrievedInstance.sum());
请注意,如果您将任何内容存储在原始对象的 closures 中而不是实例上的 properties 中,则此方法将不起作用。