Una sinfonía en C#

Un pequeño aporte a la comunidad de habla hispana.

Tips de Javascript: Creación de objetos

Javascript es un lenguaje orientado a objetos, en teoría, pero tiene una particularidad interesante, no posee clases, con lo cual la creación de objetos se hace de otras manera que como haríamos en C#.

Formas de crear objetos número uno, literal:

La notación literal es la más común y permite declarar un objeto a partir de una expresión JSON, por ejemplo de este modo

var persona = {};
persona.nombre = 'leonardo';

console.log(persona.nombre);

image

Esto nos lleva a dos conclusiones:

  • Primero podemos crear objetos sin la existencia de una clase.

  • Segunda los objetos que creamos son mutales, notemos que hemos agregado la propiedad nombre luego de la declaración del objeto, interesante.

Es posible en la misma declaración incluir las propiedades y funciones, del siguiente modo:

var persona = {
				nombre:'leonardo' , 
				saludar:function(){ 
					return 'hola mi nombre es ' + this.nombre;}
			   };
			   
console.log(persona.saludar());

image

perfecto, es claro que  podemos declarar tanto propiedades como funciones de un objeto con una expresión literal, un JSON, nuestros objetos serán mutales y se podrán agregar más miembros en cualquier momento.

Creación de objetos a partir de funciones, forma dos:

Una forma más natural (para los que venimos de C#) de crear objetos en javascript es a partir de una función constructor, el ejemplo anterior utilizando esta técnica sería así:

Persona = function (nombre){
			this.nombre = nombre;
			this.saludar = function()
			{
				return "hola mi nombre es " + this.nombre;
			}
	};
			   
var persona = new Persona('Leonardo');
			   
console.log(persona.saludar());

y obtenemos el mismo resultado, la ventaja de esta forma es que podemos crear muchos objetos iguales, por ejemplo así:

Persona = function (nombre){
			this.nombre = nombre;
			this.saludar = function()
			{
				return 'hola mi nombre es ' + this.nombre;
			}
	};
			   
var leonardo = new Persona('leonardo');
var gabriel = new Persona('gabriel');
			   
console.log(leonardo.saludar());			   
console.log(gabriel.saludar());

y todo funciona muy bien, ahora vamos a ver un poco qué pasa en el DOM

image

Vemos algo interesante:  tanto la propiedad “nombre” como la función “saludar” se encuentran a nivel objeto y no a nivel función “Persona”, lo que significa que se crea una nueva copia de la propiedad y de la función para cada uno de los objetos que generemos a parir de la función, en principio es poco deseable.

Utilizando prototipos

La forma de tener miembros reutilizables es agregarlos al prototipo, del siguiente modo:

Persona = function (nombre){
			this.nombre = nombre;
			Persona.prototype.saludar = function()
			{
				return 'hola mi nombre es ' + this.nombre;
			}
	};
			   
var leonardo = new Persona('leonardo');
var gabriel = new Persona('gabriel');
			   
console.log(leonardo.saludar());			   
console.log(gabriel.saludar());

image

ahora si, vemos que la función saludar pertenece al prototipo (__proto__) al igual que la función constructor, lo cual implica que ambos objetos utilizan la misma copia de la función, mucho mejor.

Variables estáticas?

Algo así, la pregunta es: qué pasa si ponemos también la propiedad nombre a nivel prototipo?

Persona = function (nombre){
			Persona.prototype.nombre = nombre;
			Persona.prototype.saludar = function()
			{
				return 'hola mi nombre es ' + this.nombre;
			}
	};
			   
var leonardo = new Persona('leonardo');
var gabriel = new Persona('gabriel');
			   
console.log(leonardo.saludar());			   
console.log(gabriel.saludar());

image 

Vemos que tanto __proto__ como los dos objetos tienen el mismo valor en la propiedad “nombre” es porque al se una propiedad dentro del prototipo es siempre la misma, con lo cual va a tomar el valor que se le asignó en última instancia para todos los objetos y el prototipo, en este caso “gabriel”

Hasta la próxima.

2011-11-26 EDIT: como me comenta Carlos por mensaje privado, no es correcto acceder al prototipo en la función constructor ya que se ejecutaría con cada nuevo objeto, en contra de la idea final que es usar la misma instancia de la función, el código correcto debería modificar el prototipo por fuera de la función constructor, de la siguiente manera:

Persona = function (nombre){
			this.nombre = nombre;
	};
Persona.prototype.saludar = function(){
	return 'hola mi nombre es ' + this.nombre;
}

Gracias Carlos!

Loading