2011-05-13 40 views
6

Soy nuevo en JavaScript y trato de entender cómo debo escribir clases (mi experiencia en lenguajes OO 'regulares', como java y C++).¿Forma correcta de crear clases en JavaScript?

entiendo que tengo dos opciones:

  1. si quiero mi clase de disponer de métodos y miembros privados no puedo definirlos en el prototipo. Pero en ese caso, se construirán para cada objeto nuevo creado (problema de memoria).

  2. Si defino métodos en el prototipo de clase, no tendré encapsulado (esto es raro para mí, como desarrollador de java/C++: P).

¿Cuál de los dos métodos utiliza? ¿por qué?

+0

Lea aquí: http://www.crockford.com/javascript/inheritance.html –

+0

también esto: http://javascript.crockford.com/ private.html –

+0

Eche un vistazo a [Fundamentos de OOP] (http://stackoverflow.com/questions/5134208/jquery-oop-basics/5134494#5134494) – Raynos

Respuesta

7

Por lo tanto, no creo que haya una "respuesta correcta" a esta pregunta ... es básicamente lo que usted prefiere y cree que es mejor para su uso particular. Muchas de mis clases son "Clases estáticas", p.

var MyClassName = { 
    methodName: function() { }, 
    //... 
} 

Como nunca tengo que crear una instancia de ellos. Cuando necesito instanciar instancias múltiples, uso el método prototipo.

Si NECESITA variables privadas, podría definir una función/clase para hacer variables privadas, y los métodos que necesitan acceder a los vars privados dentro de esa función/clase. Luego, use el método prototipo para todos los métodos que no necesiten acceso a los vars privados. P.ej.

var PageClass = function() { 
    var _birthdate; 

    this.getBirthdate = function() { 
     return typeof(_birthdate) == "undefined" ? null : _birthdate; 
    } 
    this.setBirthdate = function(date) { 
     if(typeof(date) == 'object' && date.constructor == Date) { 
      _birthdate = date; 
     } 
     else { 
      throw "Invalid Argument Exception: PageClass.setBirthdate expects parameter of type 'Date'"; 
     } 
    } 
} 
PageClass.prototype.doSomething = function() { 
    alert("DOING SOMETHING"); 
} 

Hacer ambas cosas debe permitirle mantener su instanciación de peso un poco más ligero, pero aún así darle un poco de encapsulación. Hasta ahora, nunca me he molestado con los vars privados.

0

Si está utilizando el marco prototipo, será mejor que utilice su forma de implementar clases y herencia. Probablemente se estaba refiriendo a this article

Normalmente, no creo que los miembros privados se usen en javascript. (edit: No en clases instanciadas. Veo con bastante regularidad algunos "módulos" en nuestra base de código que mantienen un estado privado pero podrían verse como singletons)

La respuesta de Kevin lo resume bastante. Es técnicamente posible evitar la falta de encapsulamiento del lenguaje, pero tiene un costo si su clase va a ser instanciada mucho. También creo que necesitarías algo de trabajo para obtener una visibilidad protegida si vas a usar la herencia.

No creo que haya visto ninguna cosa privada al mirar las fuentes de extensión, por ejemplo. Ponen "// privado" sobre los métodos que deberían ser privados, lo que es una pista de que no deberían llamarse directamente. Significa que necesita más "disciplina" para escribir getters/setters si va a codificar de esta manera.

0

Por qué sí hay ... ahora.

Las respuestas anteriores son correctas para su tiempo.

Aquí está la solución nueva:

'use strict'; 

// Declare our class 
class Metadata { 

    // Declare the constructor and pass it some values - a and b are "defaults" 
    constructor(ninfo, a = 1.0, b = 1.0) 
    { 
     // Set our class variables 
     this.ninfo = ninfo; 
     this.a = a; 
     this.b = b; 

     // Define our "secret" or nonenumerable options 
     Object.defineProperty(this, 'addA', { 
      enumerable: false, 
      writable: false, 

      // Have it add our passed in value 
      value: n => this.a += n 
     }); 
    } 
} 

// Call our class and pass in some variables 
let x = new Metadata("we have a and b", 1.0); 

// Log our result if we call "addA" 
console.log(x.addA(3)); // => 4 

// Log our object 
console.log(x); // => Metadata { ninfo: 'we have a and b', a: 4, b: 2 } 

// Log our object 'for real' 
console.log(require('util').inspect(x, { showHidden: true, depth: null })); 

// result 
// Metadata { 
//  ninfo: 'we have a and b', 
//  a: 4, 
//  b: 2, 
//  [addA]: { [Function: value] [length]: 1, [name]: 'value' } } 
Cuestiones relacionadas