跟踪更改的Javascript对象封装

时间:2011-01-06 23:30:52

标签: javascript design-patterns node.js containers wrapper

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

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

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

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

深度克隆不是一种选择,因为我正在尝试编写这样的包装器以避免这样做。

只有在没有其他解决方案时才应考虑序列化的解决方案。

使用的一个例子是

var foo = state.get();
// change state
state.update(); // or state.save();
client.tell(state.recentChange());

jsfiddle代码段可能会有所帮助:http://jsfiddle.net/Raynos/kzKEp/

似乎实现内部哈希以跟踪更改是最佳选择。

[编辑]

澄清这是在服务器上的node.js上进行的。唯一改变的是该解决方案可以特定于V8实现。

5 个答案:

答案 0 :(得分:2)

您必须使用一个类来包装所有嵌套对象,该类会在发生更改时报告您。问题是,如果您只将观察者放在第一级对象中,您将只接收该对象中包含的属性的通知。

例如,假设你有这个对象:

var obj = new WrappedObject({
    property1: {
        property1a: "foo",
        property1b: 20,
    }
})

如果你没有包装porperty1中包含的对象,你只会收到property1的“获取”事件,就这样,因为当有人运行obj.property1.property1a = "bar"时你唯一的互动就是将与obj一起使用,当它要求property1中包含的对象的引用时,修改将在未观察到的对象中发生。

我能想象的最好的方法是在包装第一个对象时迭代所有属性,并为每个typeOf(property) == "Object"递归构造一个包装器对象。

我希望我对你的问题的理解是正确的。抱歉,如果没有!这是我的第一个答案:$。

答案 1 :(得分:2)

剥离此问题的javascript方面,只有三种方法可以知道某些内容是否已更改:

  1. 保留副本或陈述以与之比较。
  2. 观察在途中发生的变化。
  3. 收到有关更改的通知。
  4. 现在将这些概念带回javascript,您有以下模式:

    1. 复制:深度克隆,完整序列化或散列。
    2. 观察:强制使用setter,或者点按javascript引擎(不太适用)
    3. 通知:修改进行更改以发布事件的代码(同样,不太适用)。
    4. 看到你已经排除了深度克隆和使用setter,我认为你唯一的选择是某种形式的序列化......请参阅hash implementation here

答案 2 :(得分:1)

有一种名为 reactive programming 的东西类似于你所要求的东西,但它更多涉及并且可能是过度杀伤。

好像你想保留价值观,对吗?只要您将更改重置为setter函数,这不应该太难。当然,这在javascript中比在其他一些语言中更难。真正的私人领域需要巧妙地使用闭包。

假设你可以完成所有这些,只需将这样的东西写入setter。

function setVal(x)
{
    history.push(value);
    value = x;
}

答案 3 :(得分:1)

您可以使用processing.js使用的解决方案。 编写正常访问包装对象的脚本......

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));

答案 4 :(得分:0)

node-proxy似乎通过在整个对象周围包装代理来实现这种方法。我将详细介绍它的工作原理。

https://github.com/samshull/node-proxy