2017-06-29 85 views
1

我目前正在編寫一個工具來監視使用Proxy對對象所做的更改。 因此,我有一個函數watchObject,它將一個對象作爲參數並將其包裝在代理中,其中對應於對象更改的處理程序調用debugger;。這watchObject主要基於這個question接受的答案。在Javascript:如何檢測變量的引用何時發生變化

設置陷阱讓definePropertydeleteProperty處理工作得很好,當對象僅修改。
但是,當引用被替換時,處理程序不會被調用,並且繞過它的代理服務器將丟失。

讓我們考慮包含對象a關鍵foo
var a = { foo: "bar"};

例如下面將調用一個調試器斷點這是我的陷阱裏:

  • a.foo = "Hello"
  • delete a.foo
  • a.baz = "Hi" 等..

但後來調用:a = {keyOne: "one"}將不會觸發斷點,並且對上述示例(否則會觸發斷點)的後續調用將不會再調用斷點。

所以我想知道是否有辦法檢測到如下操作:a = {keyOne: "one"}是爲了監視變量的引用更改並能夠在新引用的對象上重新創建代理對象。另外,由於監視對象變化的整個過程旨在簡化調試,因此解決方案必須對涉及的代碼無損壞。
使用代理是偉大的,因爲它只攔截並不改變對象包裝的整體行爲。

+0

你也許可以,如果你把它包裝在一個額外的對象,聽上到。 – ankr

+0

您是否嘗試過使用您的js引擎的實際調試器API? – Bergi

+0

「非破壞性」是什麼意思?即使你的代理解決方案需要改變一些代碼來包裝一個特定的對象。 – Bergi

回答

2

我想給這個一杆...

它看起來像你想捕捉對象本身,而不是方法。

由於對象的變量將被設置爲窗口的屬性或另一個對象,我們可以使用一個函數來定義與所需的變量名稱的窗口上的獲取和設置(或對象):

function trackedProxy(name, val, _this){ 
    let handler = {} // place your property traps here 
    let _privateObject = val 
    let _privateProxy = new Proxy(_privateObject, handler) 

    Object.defineProperty(_this, name, { 
    get: function() { 
     return _privateProxy; 
    }, 
    set: function(value) { 
     console.log("object changed") 
     // Do something 
     return _privateObject = value; 
    } 
    }); 
} 

//build one with invocation of the function, but do not set as equal to a var or you will have the same issue. 
//**bad! - var a = trackedProxy('a',{keyOne: "one"},this) 
trackedProxy('a',{ foo: "bar"}, this) 

console.log(a) 
//Proxy{ foo: "bar"} 

a={keyOne: "one"} 
//Object changed 

console.log(a) 
//Proxy{keyOne: "one"} 

請記住,在完成此操作後,您無法重新定義窗口上的屬性。

我希望這有助於:)

+0

Hello Joseph, 我沒有想到這樣的解決方案。這看起來不錯,我會測試它。 謝謝:) –

+0

但是,我只有兩個問題:_privateObject的目的是什麼? 'name'和'val'參數有什麼區別? –

+0

_privateObject在函數的名稱空間中存儲一個私有變量,只能通過函數內部的一個例程進行更改。我們需要在JavaScript中使用它,因爲getters和setter不能在具有相同名稱的變量的屬性中定義。 (無法創建var a) –