Share on FacebookTweet about this on TwitterShare on Google+

Si desarrollamos una aplicación con JavaScript debemos tener claros conceptos como las clases o los ámbitos de las variables. JavaScript es un lenguaje muy particular en estos aspectos, así que este post pretende aclarar conceptos para poder desarrollar una aplicación en JavaScript con una arquitectura correcta.
Una vez queda esto claro se puede optar por utilizar herramientas que nos ayuden en nuestro trabajo como templates, enrutadores, frameworks MVC… pero eso ya es otra historia otro post.

Variables en JavaScript

Ámbito de las variables
Las variables en JavaScript son locales o globales. El único bloque donde se define la visibilidad de una variable en JavaScript es la función. En JavaScript no existen modificadores de tipo public, private o protected ni namespaces.

En el caso siguiente, el alert no mostraría texto, ya que la variable mensaje está definida dentro de la función:

En este caso sí mostraría el mensaje, ya que la variable es global (definida fuera del ámbito de la función):

Ojo, en este caso la variable mensaje también es global, ya que está definida sin la palabra reservada var, y el funcionamiento del código será igual al caso anterior:

El motor de JavaScript realiza siempre dos pasadas en el código. La primera pasada le sirve para ver el ámbito de las variables, en el segunda pasada ejecuta el código. En este caso, el primer console.log mostrará: mensaje is undefined

En este caso, el primer console.log mostrará Error: mensaje is not defined No se ejecutará ningún código posterior.

Funciones y variables
Es práctica habitual definir todas las variables separadas por comas en la parte superior. Viendo el siguiente código podemos ver que las funciones se pueden asignar a variables, no solo sirven para agrupar bloques de código.
En este caso definimos la variable funcionA mediante una función anónima (ya que el nombre de la función carece de importancia).

Variables y objetos
Las variables globales en JavaScript realmente son propiedades del objeto window. Muchas de estas propiedades contienen objetos, métodos, elementos del DOM y otras variables.

Otro ejemplo:

Objetos en JavaScript

En la mayoría de los lenguajes, los objetos están basados en clases, mientras que en JavaScript se basan en prototipos. Cuando trabajas con clases, creas la clase y luego instancias un objeto de dicha clase mediante su constructor. En JavaSript el propio prototipo es un objeto en si mismo.

Sistema basado en clases:


Sistema basado en prototipos:


Es más rápido y sencillo mediante prototipos cuando trabajamos con un solo objeto. Pero, ¿qué pasa si hay varios objetos del mismo tipo?

Sistema basado en clases:
1. Definimos la clase y su constructor:

2. Instanciamos los objetos:

Sistema basado en prototipos:

1. Definimos el prototipo:

2. Definimos el constructor

3. Asociamos el constructor con el prototipo

4. Instanciamos los objetos

Object.create
En vez de usar el operador new, en JavaScript se suele utilizar el método Object.create por resultar más natural.

Podemos crear una función que factorice, para que el código quede más limpio:

Funciones en JavaScript

El tema más complejo de JavaScript son las funciones. Pueden almacenar variables, reciben atributos, se pueden pasar como parámetros en llamadas a otras funciones… Además se usan como herramienta para controlar el ámbito de visibilidad de las variables, así como para crear métodos y variables privadas. Resumiendo, nada que ver con otros lenguajes de programación como Java.
Las funciones son objetos de primera clase en JavaScript.

Funciones y funciones anónimas

Normalmente una función vendría así:

Pero esta misma función podríamos decidir guardarla en una variable:

Si la función la guardamos en una variable, el nombre de la función puede ser redundante, por lo que podemos utilizar lo que se llaman anonymous functions o funciones anónimas:

Fíjate que para que la función se ejecute, tenemos que llamar a la variable. Ojo, la función puede tener parámetros así que haríamos la llamada de forma similar:

Funciones anónimas autoejecutables

A menudo se utilizan las funciones en JavaScript como un método de tener todas nuestras variables y métodos definidos en un namespace distinto del global. Esto es muy útil cuando se utilizan librerías de terceros o si nuestro código JavaScript es suficientemente extenso y por tanto propenso a que haya colisiones entre variables.

El código anterior tiene una “pega” y es que sería mejor no tener que definir una función, guardarla en una variable y luego tener que ejecutar la función. Ahí es donde entran las funciones anónimas autoejecutables aportando sencillez a nuestro código:

La función saludo, que hemos definido anteriormente:

Quedaría como:

Imagina que trabajas con jQuery y Prototype. Ambas usan el $ como variable y en principio la librería que añadamos en último lugar será la “propietaria” de la variable $. Podemos utilizar una función anónima autoejecutable para que jQuery use la variable $ en un bloque determinado de código:

Module patterns

Una vez queda claro el concepto de funciones anónimas autoejecutables vamos a intentar trabajar con varios ficheros en los que cada fichero correspondería con un namespace diferente. Se trata de un patrón de diseño bastante habitual avanzado del mismo. Pensemos en un SPA: su código puede ser bastante extenso y no puede ser definido en un solo fichero. Sería ideal dividirlo en varios módulos, cada uno de ellos manejaría sus propias variables, propiedades o métodos.

Podemos probar el código anterior y compruebar que:
Las propiedades de prisionero serán nombreCompleto y sentencia.
Las variables nombre y apellido son inaccesibles desde fuera del código.
Las propiedades se pueden modificar desde fuera del código.
Podríamos añadir alguna variable nueva, simplemente con un código del tipo:

Una vez que se ejecuta el código de la función anterior, las variables se destruyen por el recolector de basura. Las propiedades nombreCompleto y sentencia guardan una copia de las mismas, esto es, que si pudieramos modificar el valor de las variables, las propiedades no cambiarían.
Puedes ver todo este análisis en este jsfiddle.

Closures

Para que las propiedades se recojan de “forma dinámica” necesitaremos utilizar closures.
¿Qué es un closure?
En algunos lenguajes como C, la gestión de la memoria la hace el programador. En otros como Java y JavaScript está automatizada mediante un garbage collector. Así, cuando una función termina su ejecución (como la del ejemplo anterior), lo que hace el garbage collector es eliminar todas las variables de la función, a fin de cuentas ya no necesite acceder a las mismas.
Un closure es el proceso de evitar que el garbage collector borre una variable de su memoria, accediendo a la misma desde fuera del contexto en el que fue creada.
En el siguiente código vemos como la variable miNombre no se pierde por el recolector de basura ya que una vez ejecutada la función anónima, se sigue haciendo referencia a la variable por medio del método nombre:

Ojo! No podemos utilizar this, y sobreescribir el método setNombre de modo que quede:

El operador this, en este caso se refiere a lo que queda después de haber ejecutado la función anónima (esto es, solo al return). ¿Se entiende o es un poco lío?
Puedes jugar con el código desde este jsfiddle.
Veamos otro ejemplo de que hay que tener cuidado con el operador this. Este código funciona como esperamos:

Sin embargo si hacemos una llamada ajax, this pasaría a ser el objeto ajax:

La solución pasaría por guardar una copia de this, antes del cambio de contexto:

Leave a Reply

Your email address will not be published. Required fields are marked *