2009-09-17 17 views
28

Duplicar posibles:
Use of 'prototype' vs. 'this' in Javascript?funciones de instancia de JavaScript comparadas con las funciones del prototipo

Mi comprensión de los diferentes tipos de funciones de JavaScript son los siguientes:

function MyObj() { 
    this.propOne = true; 
    this.publicInstanceFunc = function() { 
     if (propOne) 
      return 'public instance function'; 
    } 
    function privateFunc() { 
     return 'private function only visible inside this constructor'; 
    } 
} 

MyObj.prototype.protoFunc = function() { 
    if (this.propOne) 
     return 'prototype function shared amongst all instances of MyObj'; 
} 
  1. Son estos correctos?
  2. ¿En qué casos se deben poner funciones en el prototipo (por ejemplo, protoFunc) frente al constructor (por ejemplo, publicInstanceFunc)?
  3. ¿Está utilizando this la forma correcta de acceder a las propiedades dentro de las funciones del prototipo?

Respuesta

49

En realidad se puede añadir otro nivel de privilegio a través de envolver todo el asunto en una función de aplicación directa:

var MyObj = (function() { // scoping 
    var privateSharedVar = 'foo'; 

    function privateSharedFunction() { 
     // has access to privateSharedVar 
     // may also access publicSharedVar via explicit MyObj.prototype 
     // can't be called via this 
    } 

    function MyObj() { // constructor 
     var privateInstanceVar = 'bar'; 
     this.publicInstanceVar = 'baz'; 

     function privateInstanceFunction() { 
      // has access to all vars 
      // can't be called via this 
     }; 

     this.publicInstanceMethod = function() { 
      // has access to all vars 
      // also known as a privileged method 
     }; 
    } 

    MyObj.prototype.publicSharedVar = 'quux'; 

    MyObj.prototype.publicSharedMethod = function() { 
     // has access to shared and public vars 
     // canonical way for method creation: 
     // try to use this as much as possible 
    }; 

    return MyObj; 
})(); 

Sólo propiedades 'público' se puede acceder desde el exterior a través this.

Por razones de rendimiento, debe evitar lo que llamé métodos de "instancia": para cada uno de estos, se debe crear un nuevo objeto de función para cada instancia MyObject, mientras que solo hay un único objeto de función por método "compartido".

+0

Gracias! ¡Buena respuesta! – mcjabberz

+0

siento resucitar esta pregunta/respuesta, pero ¿tiene algo especial que envolver esa función externa en parens? p.ej. cómo es (función() {})(); diferente de la función() {}(); – Matt

+0

@Matt: los paréntesis externos obligan a interpretar el literal de la función como una expresión en lugar de una declaración; son innecesarios en este caso porque la tarea ya obliga a esta interpretación, pero sin ella, debería obtener un error de sintaxis si omite los parens – Christoph

3

1) Sí, su código es correcto.

2) Utilizo funciones definidas dentro de la función constructora cuando quiero acceder a otros miembros definidos de forma privada dentro del alcance de la propia función del constructor, por ejemplo, cuando desea crear privileged methods.

Las funciones públicas definidas en la función constructora son más costosas desde el punto de vista informático que la adición de una función simple al prototipo del objeto, pero también le dan mucha más flexibilidad.

3) Sí, si la propiedad es pública, puede acceder a ella utilizando la palabra clave this dentro de una función ampliada de prototipo, ya que this hace referencia a la instancia de su objeto.

3

En cuanto al segundo punto, extiende el prototipo para que todos los objetos ya creados obtengan el nuevo método.

Además, le permite agregar métodos a los objetos incorporados (como agregar trim() a string).

4

¿Son correctos?

Err. Bueno, depende de lo que quieras hacer. No hay un modelo canónico aceptado para implementar herencia de clase/estilo de instancia en JavaScript.

Pero esto:

if (propOne) 

es probablemente un error, en el que this.propOne es una propiedad del objeto propietario, mientras que propOne por sí mismo es una variable que no ha sido declarado (el valor predeterminado a una variable global, pero generalmente es una incorrección).

¿En qué casos se deben poner funciones en el prototipo (por ejemplo, protoFunc) vs. en el constructor (por ejemplo, publicInstanceFunc)?

Una función establecida en el prototipo es la misma función compartida entre todos los objetos. La única forma en que puede averiguar a qué instancia pertenece es leyendo 'esto' cuando se lo llama.

Una función establecida en 'this' en el constructor es una función nueva para cada instancia del MyObj. Posiblemente pueda usar esto como una forma alternativa de vincularse al objeto propietario en función de cierres en lugar de 'esto', lo que puede ahorrar la escritura de cosas vinculantes de funciones. Es un estilo diferente de orientación a objetos que normalmente no se mezclaría con el estilo basado en este.

Cuestiones relacionadas