2012-05-01 10 views
5

En JavaScript puede componer objetos utilizando algún tipo de función extend.Cómo evitar conflictos de nombres al componer objetos

Por ejemplo puede ser que tenga una clase observable que expone un conjunto de métodos públicos (get, push, set, increment, get, etc)

En este caso lo observable también pasa a ser un EventEmitter por lo que también expone un conjunto adicional de métodos públicos (emit, on, removeListener, etc)

Ambas clases tienen propiedades subrayado el prefijo internos que almacenan el estado. El eventemitter usa _events para almacenar manejadores de eventos y los usos observables _state y _id para almacenar el estado y la identificación.

Ahora cuando se crea un modelo que utiliza la composición de objetos al igual que

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

Esto causa un problema porque Observable ya se utiliza la propiedad interna _state y ahora hay un nombre choque.

Considero feo simplemente "tener que saber" qué objetos dependen de qué propiedades internas de la mixin funcionen de forma segura.

¿Cómo se evita mezclar en dos objetos que usan el mismo nombre de propiedad interna?

Lo ideal sería que esto se resuelva con los nombres privados de ES6, pero no podemos hacer eso todavía y no podemos emularlos sin perder el rendimiento. A menos que pueda proporcionar una emulación de nombre ES6 que no tenga una gran penalización de rendimiento, no estoy interesado en esas soluciones.

Una alternativa sería utilizar cierres o bind, pero luego se estaría recreando las funciones para cada instancia con una penalización de rendimiento significativo. Otra alternativa sería las propiedades internas del espacio de nombres como __eventEmitter_events y __observable_state. Eso es feo y reduce la probabilidad de un conflicto de espacio de nombres, no lo elimina.

+0

buena pregunta ..! – Alnitak

+0

Si la memoria sirve, ExtJS la resuelve en la canalización de creación de objetos instanciando un EventEmitter como una propiedad suspendida del Observable, y aplicando todos los métodos * public * del EventEmitter al Observable usando el enlace de función, mientras mantiene todo el estado privado dentro de ese EventEmitter . Codificaría un ejemplo, pero me voy AFK ... dame una hora? – zetlen

+0

@zetlen tenga en cuenta que el proxy de todos los métodos públicos que utilizan el enlace de funciones significa que crea un conjunto completo de nuevas funciones para cada instancia observable. como se mencionó, esto tiene la penalización de rendimiento exacta como emulación de nombres privados. Esta es una solución, pero queremos evitarla por razones de rendimiento – Raynos

Respuesta

0

La solución trivial es "espacios de nombres"

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