2012-09-28 64 views
11

Teniendo en cuenta los patrones de creación de objetos con propiedades particulares, una forma de hacerlo es:cómo tener el patrón de creación de objetos JavaScript con métodos reutilizables y propiedades privadas?

function MyStack(){ 
    var list = [], 
     index = 0; 

    this.push = function(val){ 
     return list[index++] = val; 
    }; 
    this.pop = function(){// ...} 
} 

var stack1 = new MyStack();  stack1.push(5); 
var stack2 = new MyStack();  stack2.push(11); 

problema con esto: Cada instancia de la pila tiene su propia copia de los métodos 'empuje' y 'pop'.

Otra forma de implementar método constructor es:

function MyStack(){ 
    this.list = []; 
    this.index = 0; 
} 
MyStack.prototype = { 
    insert: function(val){ 
      return this.list[this.index++] = val; 
     }, 
    pop:function(){//...} 
} 

problema aquí: Perdemos la privacidad de la lista y el índice.

¿Hay alguna manera de que podamos tener ambos métodos reutilizados entre las instancias y la privacidad de las propiedades?

Entiendo que podemos tener esto para los métodos que no operan en ningún estado del objeto, pero estoy hablando más acerca de los métodos que sí operan en el estado.

+0

Puede dar a cada instancia una ID aleatoria y almacenar sus propiedades privadas en algún tipo de estructura de datos. Pero sugiero que simplemente olvide las propiedades privadas si usa funciones de constructor. JavaScript no está diseñado para eso y cualquier solución alternativa tiene alguna desventaja. –

+0

@FelixKling así que digamos que tenemos un DS auxiliar, Like {id1: {list: [3,4], currentIndex: 2}, id2: {list: [2,1,4], currentIndex: 3}} .. .incluso en MyStack.prototype.insert = function (val) {currState = this.auxiliaryDS [this.id]; this.currState.list.push (val) .. De nuevo, no es realmente privado. – sbr

+1

Puede definir el almacén de datos y la función de constructor dentro de una función y solo exponer la función de constructor.El almacén de datos sería entonces privado y no sería accesible desde el exterior. Sí, la ID sería accesible, pero incluso podría generar un nombre de propiedad aleatorio para esto si quisiera ofuscarla. Como dije, JS no está hecho para esto y todo lo que hagas será raro o complejo. La documentación adecuada es más valiosa IMO. Aquí puede encontrar bastantes preguntas relacionadas: http://stackoverflow.com/search?q=javascript+private+instance+variables+and+prototype+methods –

Respuesta

1

Sí. He editado este código por lo que en realidad es completamente funcional ya que tuviste la intención de que funcione. Me parece un poco redundante, pero proporciona la capacidad de proporcionar una interfaz pública, pero para mantener sus variables privadas y controlar la forma en que el usuario interactúa con ellas.

function MyStack(){ 
    var list = []; 
    var index = 0; 

    this.getIndex = function(){ 
     return index; 
    } 
    this.setIndex = function(val){ 
     index = val; 
    } 
    this.list = function(val){ 
     if(val){ 
      // setter if a value was provided. Illustrating how you can control 
      // index, which I assume is the point of having these things private 
      // to begin with 
      return list[this.setIndex(this.getIndex() + 1)] = val; 
     } 

     // always return list - acts like a getter 
     return list; 
    } 
} 
MyStack.prototype = { 
    insert: function(val){ 
      return this.list(val); 
     }, 
    pop:function(){} 
} 

var stack1 = new MyStack();  
stack1.insert(5); 
var stack2 = new MyStack();  
stack2.insert(11); 
0

Creo que en ambos enfoques que mencionó, cuando se crea un objeto utilizando un patrón de constructor, las propiedades se copiarán a sus objetos. Esto lo mencionó para el primer enfoque como la preocupación. Siento que lo mismo se aplicará para el segundo enfoque también junto con su preocupación en este enfoque.

En general vamos al segundo enfoque que mencionaste cuando queremos extender las propiedades de "MyStack" a alguna otra clase.

Digamos que desea extender su MyStack clase para MyTest, como a continuación

var dummy = function(); 
dummy.prototype = MyStack.prototype; 
var MyTest = function(){ 
}; 
MyTest.prototype = new dummy(); // Assigning MyStack properties to MyTest 
var obj = new MyTest(); 
1

Usted debe comprobar fuera de John Resig Simple Javascript Inheritance. Es una gran lectura, y se ha extendido para proporcionar soporte para partes privadas, acertadamente llamado Privates.js;

+0

No sabía nada de Privates.js. – sbr

1

Una función de constructor puede devolver cualquier objeto (no es necesario este). Se podría crear una función de constructor, que devuelve un objeto proxy, que contiene métodos proxy para los métodos "reales" del objeto de instancia "real". Esto puede sonar complicado, pero no lo es; aquí es un fragmento de código:

var MyClass = function() { 
    var instanceObj = this; 
    var proxyObj = { 
     myPublicMethod: function() { 
      return instanceObj.myPublicMethod.apply(instanceObj, arguments); 
     } 
    } 
    return proxyObj; 
}; 
MyClass.prototype = { 
    _myPrivateMethod: function() { 
     ... 
    }, 
    myPublicMethod: function() { 
     ... 
    } 
}; 

Lo bueno es que la creación de proxy puede ser automatizado, si definimos una convención para nombrar los métodos protegidos. Creé una pequeña biblioteca que hace exactamente esto: http://idya.github.com/oolib/

+0

Esto me parece increíblemente extraño. ¿Podría explicarlo un poco más? También leo los documentos de tu lib tratando de asimilarlos, pero no veo exactamente qué está haciendo el objeto proxyObj – netpoetica

+0

Puedes instanciar MyClass con 'myObj = new MyClass();'. myObj será el proxyObj: tendrá solo 1 miembro, llamado myPublicMethod. ¿Es esto comprensible, o tienes más preguntas? Con mucho gusto ayudaría. – slobo

Cuestiones relacionadas