Una sinfonía en C#

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

jQuery extend, utilidad para combinar valores de objetos

Muchas veces nos encontramos desarrollando una función que acepta varios parámetros y hemos decidido que la forma de pasar estos parámetros sea a través de un objeto que los represente, el problema es cuando estas opciones son muchas y no es indispensable que quien usa la función indique todos los parámetros sino que tenemos un grupo de valores por omisión y tenemos que determinar qué valores indica el usuario de la función y cuáles tenemos que tomar de los que son por “default”, bien, nuestra querida jQuery tiene una utilidad para esto, extend

jQuery.extend

El tema es así, tenemos un objeto que contiene las propiedades, pero también tenemos otro objeto en el cual sus propiedades son valores por omisión, vamos a ver cómo combinamos sus valores son jQuery

(function (){
	//no indicamos ninguna opción
	var opcionesDeUsuario = {};
	//estas son nuestras opciones por omisión
	var opcionesPorDefecto = {nombre:'leonardo', apellido:'micheloni'};
	//utlizamos jQuery.extend para "mergear" ambos objetos
	$.extend(opcionesPorDefecto, opcionesDeUsuario);
	//el resultado queda en opcionesPorDefecto
	console.dir(opcionesPorDefecto);
})();

Lo ejecutamos y vemos que resulta

image

Pero es el caso más simple, no indicamos nada, vamos a ver si indicamos alguna de los valores qué pasa

(function (){
	//indicamos el valor de la propiedad "nombre"
	var opcionesDeUsuario = {nombre:'gabriel'};
	//estas son nuestras opciones por omisión
	var opcionesPorDefecto = {nombre:'leonardo', apellido:'micheloni'};
	//utlizamos jQuery.extend para "mergear" ambos objetos
	$.extend(opcionesPorDefecto, opcionesDeUsuario);
	//el resultado queda en opcionesPorDefecto
	console.dir(opcionesPorDefecto);
})();

image

Perfecto, reemplazó el valor de la propieada nombre tal cual indicamos, vamos por una más difícil, indicar una propiedad que no está definida en el objeto que tomamos por omisión

(function (){
	//indicamos el valor de la propiedad "nombre" y una nueva propiedad "edad"
	var opcionesDeUsuario = {nombre:'gabriel', edad:35};
	//estas son nuestras opciones por omisión
	var opcionesPorDefecto = {nombre:'leonardo', apellido:'micheloni'};
	//utlizamos jQuery.extend para "mergear" ambos objetos
	$.extend(opcionesPorDefecto, opcionesDeUsuario);
	//el resultado queda en opcionesPorDefecto
	console.dir(opcionesPorDefecto);
})();

image

y funciona perfectamente, ahora la variable opcionesPorDefecto tiene un “merge” entre sus valores iniciales y aquellos que sobre-escribió y agregó la variable opcionesDeUsuario.

Hasta la próxima.

Funciones autoejecutables en Javascript

Siguiendo con la serie “ahora tengo que programar Javascript aunque no quiera” vamos a ver una funcionalidad extraña pero interesante, las funciones autoejecutables.

Funciones normales

Una función normal en Javascript se declara de manera bastante clásica con el detalle que no podemos definir visibilidad ni valor de retorno, por ejemplo, una función que muestra un mensaje sería algo así:

function mensaje(){
	alert("mi nombre es Bond");
}

Simple, la función tiene un nombre y un cuerpo, opcionalmente podemos ponerle parámetros, del siguiente modo:

function mensaje(s){
	alert(s);
}

Si quisiéramos que se ejecute inmediatamente haríamos los siguiente:

function mensaje(s){
	alert(s);
}

mensaje("mi nombre es Bond");

Y listo

image

Pero qué sentido tiene nombrar una función que se va a ejecutar sólo cuando se inicia la página para invocarla en la siguiente línea? poco, entonces llegan las funciones autoejecutables.

Funciones autoejecutables

La idea es que la misma función se ejecuta en cuanto está preparada para ser ejecutada, la sintáxis es algo extraña pero vamos a ver el mismo ejemplo en una función autoejecutable.

(function (){
	alert("mi nombre es Bond");
})();

y obtenermos el mismo resultado

image

vamos a explicar esta expresión.

Si analizamos a partir de “function” es una función como cualquier otra, y de hecho lo es, pero sin nombre, el nombre podemos ponerlo o no.

function (){
	alert("mi nombre es Bond");
}

Vemos que toda esta función se encierra entre paréntesis

(function (){
	alert("mi nombre es Bond");
})

y por último dos paréntesis y punto y coma para invocarla

(function (){
	alert("mi nombre es Bond");
})();

Pasar parámetros a una función autoejecutable

El ejemplo anterior pasando el parámetro a la función autoejecutable sería así

(function (s){
	alert(s);
})("mi nombre es Bond");

image

y funciona perfecto, vemos que al final, en los paréntesis (la invocación a la función) pasamos los parámetros.

Hasta la próxima.

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!

Tips de Javascript: parseInt

Muchas veces nos encontramos con la necesidad de convertir un valor que inicialmente es texto en un entero, entonces rápidamente se nos ocurre ir a buscar la función parseInt de javascript, bien, existe un detalle muy interesante acerca del comportamiento de la misma, veámos un ejemplo.

var valor = "10";
var numero = parseInt(valor); 
console.log(numero);

image

(con F12 activamos el IE Develpoer Toolbar que nos permite tener acceso al objeto console)

Esto está muy bien, es el resultado esperado, pero qué pasa si hacemos lo siguiente.

var valor = "010";
var numero = parseInt(valor); 
console.log(numero);

image

chan!! nos da 8.

parseInt infiere que el valor que ingresamos está en base octal, y resulta que 10 en octal es 8 la forma correcta de evitar esto es siempre indicar la base como segundo parámetro de la función parseInt como se indica en la documentación de Mozilla.

var valor = "010";
var numero = parseInt(valor, 10); 
console.log(numero);

image

y problema solucionado, hasta la próxima.