2011-01-06 55 views
4

是否可以創建一個對象容器,其中可以跟蹤更改追蹤變化的Javascript對象封裝

所述對象是一個複雜的嵌套數據對象。 (符合JSON)。

的包裝可以讓你得到該對象,並保存更改,沒有明確闡明什麼變化

是否存在一種設計模式,對於這種封裝

深克隆是不是因爲一個選項我試圖寫一個這樣的包裝來避免這樣做。

只有在沒有其他解決方案時才應考慮序列化的解決方案。

使用的一個例子是

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

一個的jsfiddle片斷可能會有所幫助:http://jsfiddle.net/Raynos/kzKEp/

這似乎是實現內部哈希保持變化的軌跡是最佳的選擇。

[編輯]

爲了澄清這是在服務器上的node.js actaully完成。唯一改變的是解決方案可以針對V8實現。

+0

這應該不是什麼大問題。但是你能否更具體地瞭解showChanges函數的格式?例如,如果一個字符串從「Joe」更改爲「Ann」,您希望如何顯示該字符串?我發現你說foo被改變了1,而不是說foo從10改變爲1(或者foo的起始值是什麼)。 – Zevan 2011-01-07 00:05:02

+0

@Zevan格式不相關。我對如何在內部進行跟蹤更感興趣。任何格式的名稱是x,但現在y是足夠的 – Raynos 2011-01-07 00:12:08

+0

這樣的事情是這樣的:{person:{name:「Joe」,hobby:「Guitar}}基本上是一個嵌套的對象。人名 - >名稱已更改或名稱已更改? – Zevan 2011-01-07 00:30:59

回答

2

甩開這個問題的JavaScript方面,只有三條途徑知道,如果事情已經改變:

  1. 保留副本或表示與比較。
  2. 觀察在途中發生的變化。
  3. 收到變更通知。

現在把這些概念回到JavaScript和您有以下模式:

  1. 複製:無論是深克隆,全系列化,或哈希。
  2. 觀察:強制使用setter,或者點擊進入javascript引擎(不是很適用)
  3. 通知:修改使更改發佈事件的代碼(再次,不太適用)。

鑑於您已經排除了深層克隆和使用setter,我認爲您唯一的選擇是某種形式的序列化...請參閱hash implementation here

1

有一種叫做 reactive programming的東西類似於你問的東西,但它涉及更多,可能會矯枉過正。

看來你想保留一個值的歷史,對嗎?只要你改變一個setter函數,這應該不會太難。當然,這在JavaScript中比在其他一些語言中更困難。真正的私人領域需要巧妙地使用閉包。

假設你可以做所有這些,只需在setter中寫下類似的內容即可。

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

如何在不克隆值的情況下實現此目的,因爲它的指針到一個複雜的數據結構,我的意思是getter只是返回一個對象,Object.someValue可以在不需要通過setter的情況下改變,因此依賴於某種更新機制 – Raynos 2011-01-06 23:44:50

2

您必須將所有嵌套對象封裝爲一個類,該類會在出現變化時報告您。問題是,如果您只將觀察者放在第一級對象中,則只會收到此對象中包含的屬性的通知。

例如,假設你有這樣的對象:

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

如果不換行包含在porperty1對象,你只收到一個「獲取」事件property1,只是,由於當有人運行obj.property1.property1a = "bar"時,與obj的唯一交互作用是當它請求包含在property1中的對象的引用,並且修改將發生在未被觀察的對象中。

我能想到的最佳方法是在包裝第一個對象時迭代所有屬性,併爲每個typeOf(property) == "Object"遞歸構造一個包裝對象。

我希望我對你的問題的理解是正確的。不好意思這是我的第一個答案:$。

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