2010-02-05 14 views

Respuesta

2

JavaScript no utiliza clases de la misma manera que Java, C++ o similares.

Una forma de lograr su efecto es definir una función en la que se use la palabra clave , accediendo a los miembros más o menos como lo haría en Java. A continuación, utilice la nueva palabra clave al llamar a esta función para crear un objeto.

function Foo(){ //vaguely like a Java constructor 
    this.aField = 1; //define members simply by using 'this' 
    this.aMethod = methodFunction; //assign a function as a member using 'this' 
} 

function methodFunction(){ 
} 

var foo = new Foo(); //construct an object 
+0

corrigió la asignación del método; Espero que no te importe ... – Christoph

+1

A menos que uses 'methodFunction' en más de una clase, definirlo fuera de' f' no tiene ningún propósito real excepto contaminar el alcance global. –

+0

@Justin: definir 'methodFunction()' fuera del constructor definitivamente sirve para un propósito real: de lo contrario, se debe crear un nuevo objeto de función para cada instancia (es decir, una sobrecarga 'O (N)' en el número de 'f' objetos); normalmente, asignaría el método a 'f.prototype', pero hacerlo ralentizaría ligeramente la búsqueda de métodos – Christoph

4

El enfoque de la orientación a objetos más nativa de JavaScript es utilizar herencia de prototipos, pero existen muchos otros patrones, incluyendo la herencia pseudoclassical, que imita el patrón de herencia basado en clases en lenguajes como C y Java. Douglas Crockford ha escrito y hablado sobre el tema y ofrece algunas muy buenas explicaciones de cada uno. Echar un vistazo a los siguientes artículos:

Prototypal Inheritance in JavaScript

Classical Inheritance in JavaScript

10
// I like this pattern.. 

// class 
function Person(name, birthdate) { 
    this._name = name; 
    this._birthdate = birthdate; 
    /* should not do this 
    * this.getAge = function() { 
    * } 
    * as the method will be constructed 
    * for each instance, better to let it 
    * be inherited from prototype, see below 
    */ 
} 

// class methods 
Person.prototype.getBirthdate = function() { 
    return this._birthdate; 
} 

// same as above, function as a method 
Person.prototype.getAge = function() { 
    var currentDate = new Date(); 
    // age in millis 
    return currentDate - this._birthdate; 
} 

// the get age method can be a "static" 
// method on the constructor function if you pass the 
// person object 
Person.getAge = function(person) { 
    var currentDate = new Date(); 
    // age in millis 
    //no reference to this 
    return currentDate - person.getBirthdate(); 
} 

// you could use it like this 

myPerson = new Person("Steve", new Date("1980-01-01")); 
// returns age in millis 
myPerson.getAge(); 
// returns age in millis 
Person.getAge(myPerson); 

También podría utilizar una función anónima para simular privada y pública

var PersonFactory = (function() { 
    // private area, no one can alter 
    // the person cache 
    var _cache = {} 

    // public area 
    return { 
    // returns a person born now 
    getPerson: function(name) { 
     if(_cache[name]) { 
     return _cache[name]; 
     } 
     else { 
     _cache[name] = new Person(name, new Date()); 
     return _cache[name]; 
     } 
    } 
    } 
})(); 

var p = PersonFactory.getPerson("Leif"); 
p.getAge(); 
p = PersonFactory.getPerson("Leif"); 
// should be the same age/obj 
p.getAge(); 

No me gusta este patrón aunque. La advertencia de subrayado _myVariable debería ser suficiente para evitar que los usuarios de tu lib utilicen esas variables/métodos. Lo usé asignado cuando lo descubrí por primera vez debido a mi fondo de Java ... Hace que sea difícil trabajar con herencia de prototipos y puede causar pérdidas de memoria.

+0

usando un caché como usted lo describe también vence a la recolección automática de basura ya que el programador ahora tiene que asegurarse de eliminar los recursos innecesarios manualmente – Christoph

+0

Gracias, editado. – oyvindn

22

En JavaScript "moderno", hay tres métodos populares para definir objetos.

El primer método es el método clásico y sigue siendo popular debido a su simplicidad; sin embargo, es discouraged by MDC a favor del segundo método debido a la ineficiencia de tener que redefinir cada función cada vez que se crea una instancia del objeto.

// Constructor, methods and members all rolled up into one definition 
var Movie = function(name) { 
    this.name = name; 
    // Note that private members can be created using the closure property 
    var _id = +(new Date()); 

    this.getName = function() { 
     return this.name + " " + _id; 
    }; 

    this.setName = function(name) { 
     this.name = name; 
    }; 
}; 

var m = new Movie("Beerfest"); 

El segundo método es una variación de y se puede usar indistintamente con el primero. También es útil para agregar nuevos métodos a objetos existentes a través de la propiedad prototype. Los miembros privados y los métodos no son posibles en esta forma.

// Constructor is separate from its methods 
var Movie = function(name) { 
    this.name = name; 
} 

Movie.prototype.getName = function() { 
    return name; 
}; 

Movie.prototype.setName = function(name) { 
    this.name = name; 
}; 

var m = new Movie("Kill Bill"); 

El tercer método es utilizar el module pattern, lo que hace posible instanciar objetos sin tener que utilizar el operador new.

var Movie = function (name) { 
    var _id = +(new Date()); 
    var privateMethod = function() { alert(_id); }; 

    // All methods and members defined here are public 
    return { 
     name: name, 
     getName: function() { 
      return this.name + " " + _id; 
     }, 
     setName: function(name) { 
      this.name = name; 
     } 
    }; 
}; 

var m = Movie("Stackoverflow: the movie"); 

Tenga en cuenta que en los métodos primero y tercero, puede utilizar miembros y métodos de acceso privado. Pero tenga en cuenta que to use this within private methods some must happen.

0

Al utilizar una función autoejecutable anónima, puede permitir atributos/métodos públicos y privados.

Este es el modelo que más me gusta:

(function ($, MyObject, undefined) { 

    MyObject.publicFunction = function() { 
     console.log("Public function"); 
    }; 

    var privateFunction = function() { 
     console.log("Private function"); 
    };  

    var privateNumber = 0; 
    MyObject.sayStuff = function() { 
     this.publicFunction(); 
     privateFunction(); 
     privateNumber++; 
     console.log(privateNumber); 
    }; 


    // You can even nest the namespaces 
    MyObject.nestedNamespace = MyObject.nestedNamespace || {}; 
    MyObject.nestedNamespace.logNestedMessage = function() { 
     console.log("Nested namespace function"); 
    }; 

}(jQuery, window.MyObject = window.MyObject || {})); 

MyObject.sayStuff(); 
MyObject.sayStuff(); 
MyObject.nestedNamespace.logNestedMessage(); 
MyObject.publicFunction(); 

se enterara por los comentarios here y this article.

Cuestiones relacionadas