2017-06-29 100 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) –