跟踪更改的Javascript对象封装
是否可以创建一个可以跟踪更改的对象容器 所述对象是一个复杂的嵌套数据对象。(符合JSON) 包装器允许您获取对象并保存更改,而无需特别说明更改内容 是否存在这种封装的设计模式 深度克隆不是一个选项,因为我正试图编写一个这样的包装器来避免这样做 只有在没有其他解决方案的情况下,才应考虑序列化解决方案 使用的一个例子是跟踪更改的Javascript对象封装,javascript,design-patterns,node.js,containers,wrapper,Javascript,Design Patterns,Node.js,Containers,Wrapper,是否可以创建一个可以跟踪更改的对象容器 所述对象是一个复杂的嵌套数据对象。(符合JSON) 包装器允许您获取对象并保存更改,而无需特别说明更改内容 是否存在这种封装的设计模式 深度克隆不是一个选项,因为我正试图编写一个这样的包装器来避免这样做 只有在没有其他解决方案的情况下,才应考虑序列化解决方案 使用的一个例子是 var foo = state.get(); // change state state.update(); // or state.save(); client.tell(stat
var foo = state.get();
// change state
state.update(); // or state.save();
client.tell(state.recentChange());
JSFIDLE代码段可能有助于:
似乎实现内部哈希以跟踪更改是最好的选择
[编辑]
要澄清这一点,实际上是在服务器上的node.js上完成的。唯一改变的是,解决方案可以特定于V8实现。有一种称之为类似于您所问的内容的东西,但它更复杂,可能会有些过火
看起来你想保持价值观的历史,对吗?只要您将更改限制为setter函数,这应该不会太难。当然,这在javascript中比在其他一些语言中更困难。真正的私有字段需要巧妙地使用闭包
假设您可以完成所有这些,只需在setter中写入类似的内容
function setVal(x)
{
history.push(value);
value = x;
}
您必须使用一个类来包装所有嵌套对象,该类在发生更改时报告您。问题是,如果您只在第一级对象中放置了一个观察者,那么您将只收到此对象中包含的属性的通知 例如,假设您拥有以下对象:
var obj = new WrappedObject({
property1: {
property1a: "foo",
property1b: 20,
}
})
如果不包装porperty1中包含的对象,您将只收到property1
的“get”事件,因为当有人运行obj.property1.property1a=“bar”
时,您与obj的唯一交互将是当它请求引用property1
中包含的对象时,修改会发生在一个未被观察到的物体上
我能想象的最好的方法是,在包装第一个对象时迭代所有属性,并为每个typeOf(property)=“object”
递归地构造一个包装对象
我希望我对你的问题的理解是正确的。如果没有,对不起!这是我在这里的第一个答案:$。除去这个问题的javascript方面,只有三种方法可以知道是否发生了变化:
鉴于您已经排除了深度克隆和setter的使用,我认为您唯一的选择是某种形式的序列化。。。请参阅。您可以使用使用的解决方案。 编写正常访问包装对象的脚本
var foo = state.get();
foo.bar = "baz";
state.update();
client.tell(state.recentChange());
…但在运行之前,在浏览器中(或在服务器上,如果加载速度很重要),解析代码并将其转换为
var foo = state.get();
state.set(foo, "bar", "baz");
state.update();
client.tell(state.recentChange());
这还可以用于执行其他有用的操作,如运算符重载:
// Before conversion
var a=new Vector(), b=new Vector();
return a + b * 3;
// After conversion
var a=new Vector(), b=new Vector();
return Vector.add(a,Vector.multiply(b,3));
似乎
节点代理
通过在整个对象周围包装代理来实现这一点。我将更详细地了解它是如何工作的
如果没有克隆值,您将如何实现这一点。因为它是指向复杂数据结构的指针。我的意思是getter只返回一个对象。Object.someValue无需经过setter即可更改。因此依赖于某种更新机制。哦,我认为这是一个原始的东西上的翘曲器。我想你可以序列化,或者如果没有那么多字段,只是像字典一样非正式地存储它们。这应该不是什么大问题。但是,您能否更具体地说明showChanges函数的格式?例如,如果字符串从“Joe”更改为“Ann”,您希望如何显示它?我觉得很奇怪你说foo被改变了1。。。而不是说foo从10改为1(或者不管foo的起始值是什么)。@Zevan格式与此无关。我更感兴趣的是如何在内部跟踪它。任何格式,如果它的状态名称是x,但现在是y,就足够了,比如:{person:{name:{Joe],hobby:}基本上是一个嵌套对象。也就是说,你会说person->name已经改变了还是那个名字已经改变了?@Zevan你会说一些明确的话。这并不重要,它只需要明确地指出到底是什么改变了。你对这个问题的理解很好,但递归地用观察者包装子属性是一个很好的选择n选项我宁愿避免。更重要的问题是,这无法处理在对象上添加更多属性或嵌套更多属性的问题。OK,您可以使用命令模式(),定义类似于撤消管理器的内容,为对象接收的每个“get”或“set”添加命令(使用´´定义设置和´´定义设置可能与IE不兼容)。然后发送(“提交”)将所有操作发送到客户端,您可以在那里运行它们。但是,这需要您递归地包装对象:-/希望它有帮助。项目外观良好!递归覆盖get&set命令可能是最好的解决方案。这是一个有趣的解决方案。但我宁愿不通过javascript到javascript编译我的代码呃。它迫使用户在进行更改时重新编译。只是抛开想法。似乎没有任何其他解决方案可以解决您的问题