2017-03-04 23 views
3

我需要實現以下功能:如果訪問對象obj(執行obj.foo())的方法foo(),則代之以obj.bar("foo")是否有可能提前更改任何對象方法的行爲?

在這種實際情況下,我可以簡單地定義getter爲obj.foo像這樣做:

Object.defineProperty(obj, "foo", { 
    get:() => obj.bar("foo") 
}); 

但它是可以做到的,每方法提前(甚至是那些尚未定義的)?我的意思是沒有爲每一種方法提供getter。


,我可以看到現在它的完整定義,之後迭代的obj所有的方法最好的解決辦法:

for (let methodName in obj) 
    if (typeof obj[methodName] === "function" && methodName !== "bar") 
     Object.defineProperty(obj, methodName, { 
      get:() => obj.bar(methodName) 
     }); 

另一種是開始一個代碼重複行的每一個方法 - 不愉快的事情。

有沒有迭代或自我重複的解決方案?

+0

這裏是一個代理演示,我相信你在問什麼:https://jsfiddle.net/gxhscwwb/ – 2017-03-04 23:34:31

+0

@squint:謝謝,這很有幫助。你能提供一個類似的答案讓我接受它嗎? –

+1

我不知道代理給出一個體面的答案。例如,當我在代理處理程序中訪問'target [name]'時,我們並沒有以無限遞歸結束,並且我不確切知道語義允許什麼。我會讓某人對這個話題有更多的瞭解。 – 2017-03-04 23:39:33

回答

3

在現代Javascript中這樣做的方法是使用代理對象。

這是能夠(除其他外)將所有對象的屬性訪問轉發給處理程序。

因此,我們可以做這樣的事情:

let origin = { 
    bar(word) { 
     console.log('bar: ', word); 
    } 
}; 

// wrap the origin object in a Proxy handler 
let p = new Proxy(origin, { 
    get(target, prop) { 
     // wrap the value in a function 
     return() => target.bar(prop); 
    } 
}); 

p.foo(); // outputs "bar: foo" 

注意,這個假設你想要做p.foo(),而不僅僅是p.foo。它將你想要的值包裝在一個函數中。即使該屬性確實存在,它也會轉發該屬性的訪問權限。

+0

'p.bar()'會無限遞歸嗎?或者代理是否阻止了這一點? – 2017-03-04 23:41:40

+0

代理應用於已經實例化的對象,對嗎?它們看起來比'.defineProperty()'略好,因爲您可以一次覆蓋給定對象上的所有屬性。 – Ouroborus

+0

@squint否,'target'是專門提供的以避免:它是原始包裝的對象。 get函數的第三個(未使用的)參數是代理對象。 – lonesomeday

相關問題