Una sinfonía en C#

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

Tips de Javascript: Arrays 2

Para completar por ahora algunas pequeñas cosas sobre arrays en Javascript, vamos a ver unos detalles sobre cómo crearlos.

Siempre usar la notación literal []

image

El resultado es el mismo si usamos [1,2,3] o new Array(3)

image

Pero, no es lo mismo [3] que new Array(3) como podemos ver, mientras que [3] es coherente con el primer ejemplo (crea un array con un elemento de valor 3) new Array(3) crea un array de tres elementos vacíos!

image

Esto es cierto, pero si el elemento que pasamos al constructor no es un entero se comporta igual que [3]

por lo tanto

Es conveniente usar siempre la notación literal ya que el constructor de la clase Array tiene un comportamiento extraño (al menos para mí)

Hasta la próxima.

Tips de Javascript: Arrays

Vamos a ver algunas pocas características sobre arrays en Javascript, cortitas, pero interesantes.

Los arrays son objetos

Esto es obvio, en un punto todo es un objeto, pero en el caso de los arrays no hablamos de un objeto array como en C#, sino que un array es un objeto y cuando le agregamos elementos lo que estamos agregando son miembros del array, por ejemplo

var a = [1, 2, 3];

Esto no nos dice mucho, pero esto nos da una pista:

var a = [1, "hola", function() { console.log("hola");}];

Es por eso que no importa el tipo de cada elemento del array.

Podemos decir que un array es un objeto en el cual sus propiedades tienen por nombre el número de índice del array, es decir 0, 1, 2, 3; pero no podemos acceder a las propiedades con el punto (.) porque no está permitido que un identificado empiece con el mismo (a.1) , por eso hacemos

a[2]();

y es válido.

Las mismas reglas que se aplican a un objeto se aplican a un array

Claro, son objetos, es por eso que podemos iterar propiedades de un objeto del mismo modo que lo hacemos con un array como vemos en este post.

Hasta la próxima.

Tips de javascript: Por qué usar hasownproperty al iterar un objeto con for?

Hay una linda forma de obtener los miembros de un objeto cualquiera en Javascript de la que ya hablé, que básicamente es así:

var persona = {nombre: "leonardo", blog: "http://leomicheloni.com"};
for(var prop in persona){
	console.log(prop + " =  " + persona[prop]);
}

Y ocurre lo siguiente:

image

Perfecto, el problema es si por algún motivo agregamos funciones o propiedades a objetos de Javascript que pueden estar relacionados con nuestro objeto, es decir, imaginemos que queremos hacer una función en Object que retorne un string con cierto formato, así:

Object.prototype.format = function(){
	return "{"  + this + "}";
};

(de más está decir que es un ejemplo) lo que pasa ahora si corremos el código anterior es lo siguiente:

image

Esto puede pasar no sólo si agregamos funciones a Object sino que también si lo hacemos a String, o Array dependiendo del caso;

hasOwnProperty

Entonces la función hasOwnProperty nos permite saber si un miembro tal es del objeto en cuestión o de uno de sus prototipos, el ejemplo anterior sería así:

 

Object.prototype.format = function(){
	return "{"  + this + "}";
};

var persona = {nombre: "leonardo", blog: "http://leomicheloni.com"};
for(var prop in persona){
	if(persona.hasOwnProperty(prop)){
		console.log(prop + " =  " + persona[prop]);
	}
}

y santo remedio, ahora funciona.

image

Nos leemos!

Manejando dependencias en Javascript con RequireJs

A medida que nuestra aplicación crece en número de archivos Javascript y, más aún, si nuestra aplicación es una “single page application” (es decir todo ocurre en el mismo HTML y se va cargando y descargando contenido) y, por supuesto, usamos módulos para separar la aplicación en partes lógicas, empieza a ser complicado manejar algunos problemas como:

  1. Referencias que se cargan tarde
  2. Referencias que se cargan más de una vez
  3. Referencias que se cargan y no se utilizan

Es decir, nuestro proyecto tiene un tamaño interesante, unas cuantas referencias (bibliotecas, funcionalidad de diferentes partes de la pantalla, etc.) y nos encontramos con problemas de este tipo:

  1. Errores por referencias no cargadas
  2. Sobre-escritura de métodos por librerías que se cargan más de una vez, por ejemplo un plugin de jQuery que deja de andar cuando se carga jQuery una vez que cargó el plugin.
  3. Lentitud de la aplicación por esperar cargar cosas innecesarias o que aún no se necesitan, por ejemplo si ponemos todo en el la sección header del html para que se cargue siempre y evitar el problema 1.
  4. Crecimiento del costo de ancho de banda y peticiones al servidor para cargar referencias que no siempre se usan, imaginen que nuestra aplicación tiene una sección de carga de pedidos con un montón de validaciones pero no siempre se activa esa parte, cargar todo el código relativo a esa funcionalidad siempre no es lo más inteligente.
  5. etc.

RequireJs, una biblioteca para manejar dependencias en Javascript

Esta pequeña biblioteca nos ayuda solucionar estos problemas, vamos a enumerar alguna de sus características:

  • Carga dinámica de dependencias
  • Descarga automáticas de dependencias
  • Manejo de timeouts y carga de fallbacks

Adicionalmente podemos, gracias a una de sus utilidades logar

  • Minificación
  • Bundling

Primer ejemplo con Requirejs

Empecemos por lo más simple, creamos un HTML y agregamos la referencia a requirejs

<html>
<head>
<script type="text/javascript" src="http://requirejs.org/docs/release/2.1.9/minified/require.js"></script>
</head>
<body></body>
</html>

Primero indicamos a requirejs dónde empezar

Bien, este tag script va a ser la única referencia que vamos a tener, de todo lo demás se va a encargar requirejs, para eso tenemos que decirle cuál es el archivo por el cual va a comenzar nuestra aplicación, simplemente agregamos al mismo tag script un atributo

<script type="text/javascript" data-main="main" src="http://requirejs.org/docs/release/2.1.9/minified/require.js"></script>

con el atributo “data-main” le decimos a requirejs qué archivo es el punto de entrada de nuestra aplicación, como verán en este caso es “main.js” (el js siempre se omite), ahora dentro de nuestro archivo main.js hacemos lo siguiente:

require([], function(){
	console.log("hola require");
});

Bien, si lo ejecutamos imprime en la consola del navegador, vamos a explicar qué es esto

La función require

Esta función la vamos a usar cuando queramos cargar un módulo, el primer parámetro (que ahora es un array vacío) indica la dependencias, es decir, de qué otro módulos depende éste para correr, por ahora nada, el segundo parámetro es un callback que se ejecuta cuando todas las dependencias han sido resueltas, es decir si main.js depende de a.js y éste a su vez de b.js requirejs se va a encargar de cargar estas dependencias y asegurarse que están disponibles antes de llamar al callback (incluso si ya están cargadas no lo hace nuevamente) excelente, vamos a verlo.

main.js

require(["a"], function(){
	console.log("soy main");
});

a.js

define(["b"], function(){
	console.log("soy a");
});

En lugar de usar require() usamos define() ya que estamos definiendo un módulo, no pidiendo que se cargue, de eso se va a encargar requirejs cuando resuelva las dependencias.

b.js

define([], function(){
	console.log("soy b");
});

Ejecutamos el código y vemos el orden de resolución de dependencias

image

Utilizando dependencia

Hasta ahora comprobamos el orden de carga y no mucho más, lo interesante es tener funcionalidad que se cargan y poder utilizar los objetos que define cada módulo, bien, para eso cambiamos un poco el ejemplo:

main.js

require(["perro"], function(Perro){
	var roger = new Perro();
	roger.ladrar();
});

perro.js

define([], function(){
	var Perro = function(){
	};
	
	Perro.prototype.ladrar = function(){
		console.log("guauu!!");
	};
	
	return Perro;
});

lo corremos y…

image

Básicamente en main.js definimos la dependencia y luego la recibimos como parámetro del callback, dentro de perro.js tenemos que hacer return del objeto que queremos que el módulo reciba.

Cargando bibliotecas externas con Requirejs

Por supuesto que podemos cargar dependencias de terceros, la primera que viene a la mente es jQuery, pero como no es práctico copiarnos en código dentro de un módulo lo que hacemos es configurar requirejs para que cuando alguien le pida jQuery sepa qué hacer, del siguiente modo:

//configuramos requirejs para que cuando alguien pida jquery cargue la dependencia
requirejs.config({
	"paths": {
		"jquery": "http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min",
	}
});

require(["perro", "jquery"], function(Perro, $){
	var roger = new Perro();
	var saludo = roger.ladrar();
	$("body").append("<strong>" + saludo + "</strong>");
});

(modifiqué el método ladrar para que retorne un saludo)

image

básicamente llamamos al método config de requirejs y le decime qué hacer cuando le pidan jQuery.

jQuery soporta requirejs

Como muchas otras bibliotecas populares jQuery está preparada para soporta requirejs, de qué forma? bueno, si miramos el código jQuery podemos descubrirlo

	if ( typeof define === "function" && define.amd ) {
		define( "jquery", [], function () { return jQuery; } );
	}

Como vemos al final del código de jQuery esta línea se fija si existe requirejs y si es así define un módulo llamado jquery (utiliza otra sobrecarga del método define para ello)

Bien, es todo por esta vez, hay mucho más para ver, como definir dependencias entre bibliotecas de terceros y demás, pero lo dejamos para la próxima. Enjoy.