2012-05-01 89 views
5

在JavaScript中時,你可以使用某種extend功能的組合對象。如何避免名稱衝突組合對象

例如,我可能有一個observable類公開一組公共方法(getpushsetincrementget等)

在這種情況下,可觀察到的也恰好是一個EventEmitter所以它也公開了更多的公共方法(emit,on, removeListener等)

這兩個類都具有用於存儲狀態的內部下劃線前綴屬性。 eventemitter使用_events來存儲事件處理程序和可觀察用途_state_id來存儲狀態和id。

現在,當使用對象組合,像這樣

var Model = extend({}, Observable, { 
    constructor: function() { 
     // Oops, I was supposed to know Observable uses the _state name already 
     this._state = { ... } 
    }, 
    someMethod: function() { ... } 
}) 

這會導致一個問題,因爲Observable已經使用了_state內部屬性,現在有一個名稱衝突我創建了一個模型。

我會認爲這是醜陋的只是「必須知道」靠什麼內部屬性爲mixin的安全工作是什麼物體。

你如何避免在使用相同的內部屬性名的兩個對象混合?

理想的情況下,這將有ES6私人名字可以解決,但我們不能這樣做,但又不失性能,我們不能效仿他們。除非你可以提供一個ES6名稱模擬,沒有很大的性能損失我對這些解決方案不感興趣。

另一種方法是使用封閉或bind但隨後你會重新創建函數每個實例有一個顯著的性能損失。另一種替代方法是命名空間爲__eventEmitter_events__observable_state。這只是醜陋的,並減少到命名空間衝突的概率,它不會將其刪除。

+0

很好的問題..! – Alnitak

+0

如果沒記錯,ExtJS的通過實例化一個EventEmitter作爲屬性掛落觀察的,與代理所述EventEmitter的所有*公*方法到可觀察到使用功能的結合解決了其在創建對象的管道,同時保持EventEmitter內部的所有私有狀態。我會編寫一個例子,但我要AFK ...給我一個小時? – zetlen

+0

@zetlen注意到,使用函數綁定代理所有公共方法意味着您將爲每個可觀察實例創建一大堆新函數。如上所述,這具有與私人名稱仿真相同的確切性能損失。這是一個解決方案,但我們想要避免它出於性能原因 – Raynos

回答

0

瑣碎的解決方案是 「命名空間」

var state = "[email protected]~state"; 
var Model = extend({}, Observable, { 
    constructor: function() { 
     // Nice, I used a namespace and don't clash with "[email protected]~state" 
     this[state] = { ... } 
    }, 
    someMethod: function() { ... } 
})