5

In JavaScript è possibile comporre oggetti utilizzando una sorta di funzione extend.Come evitare conflitti di nomi durante la composizione degli oggetti

Per esempio potrei avere una classe observable che espone una serie di metodi pubblici (get, push, set, increment, get, ecc)

In questo caso il osservabile avviene anche per essere un EventEmitter quindi anche espone un ulteriore insieme di metodi pubblici (emit, on, removeListener, ecc)

Entrambe queste classi hanno proprietà interne sottolineatura prefissato che memorizzano lo stato. L'eventemitter utilizza _events per archiviare i gestori di eventi e gli usi osservabili _state e _id per memorizzare lo stato e l'ID.

Ora, quando ho creare un modello utilizzando la composizione di oggetti in questo modo

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

Questo fa sì che un problema perché Observable già utilizza la proprietà interna _state e c'è ora un nome scontro.

Lo considererei brutto solo per "sapere" quali oggetti si basano su quali proprietà interne per il mixin funzionare in modo sicuro.

Come evitare di mescolare due oggetti che utilizzano lo stesso nome di proprietà interno?

Idealmente questo sarebbe risolto con nomi privati ​​ES6, ma non possiamo ancora farlo e non possiamo emularli senza perdere prestazioni. A meno che non sia possibile fornire un'emulazione del nome ES6 che non abbia una grande penalizzazione delle prestazioni non sono interessato a tali soluzioni.

Un'alternativa sarebbe utilizzare le chiusure o bind ma in questo caso si ricreano le funzioni per ogni istanza con una significativa riduzione delle prestazioni. Un'altra alternativa potrebbe essere le proprietà interne dello spazio dei nomi come __eventEmitter_events e __observable_state. Questo è solo brutto e si riduce alla probabilità di uno scontro di namespace, non lo rimuove.

+0

buona domanda ..! – Alnitak

+0

Se la memoria serve, ExtJS lo risolve nella pipeline di creazione degli oggetti istanziando un EventEmitter come una proprietà appesa al Observable e trasmettendo tutti i metodi * public * dell'EventEmitter nel binding della funzione Observable using, pur mantenendo tutto lo stato privato all'interno di EventEmitter . Citerò un esempio ma andrò AFK ... dammi un'ora? – zetlen

+0

@zetlen nota che il proxy di tutti i metodi pubblici che usano il binding di funzioni significa che stai creando un sacco di nuove funzioni per ogni istanza osservabile. come detto, questo ha l'esatta penalità delle prestazioni come emulazione di nomi privati. Questa è una soluzione, ma vogliamo evitarlo per motivi di prestazioni – Raynos

risposta

0

La soluzione banale è "namespace"

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() { ... } 
})