跟踪更改的Javascript对象封装

跟踪更改的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

是否可以创建一个可以跟踪更改的对象容器

所述对象是一个复杂的嵌套数据对象。(符合JSON)

包装器允许您获取对象并保存更改,而无需特别说明更改内容

是否存在这种封装的设计模式

深度克隆不是一个选项,因为我正试图编写一个这样的包装器来避免这样做

只有在没有其他解决方案的情况下,才应考虑序列化解决方案

使用的一个例子是

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方面,只有三种方法可以知道是否发生了变化:

  • 保留一份副本或陈述以供比较
  • 观察运输过程中发生的变化
  • 被通知变更
  • 现在将这些概念带回javascript,您有以下模式:

  • 复制:深度克隆、完全序列化或哈希
  • 观察:强制使用setter,或点击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编译我的代码呃。它迫使用户在进行更改时重新编译。只是抛开想法。似乎没有任何其他解决方案可以解决您的问题