Ámbito y contexto de variables (Scope / Context) JavaScript

   En esta entrada trataré de explicar un poco en que consiste dicho ámbito y como el lenguaje trata las variables, primero que nada debemos entender algo muy sencillo, JavaScript no maneja un ámbito de variable como tal, sino que se guía por el contexto. Pero ¿como es posible?, pues veamos un simple ejemplo:
for (var i = 0; i <= 5; i++) {
 var cont = i; 
}
console.log(cont);
   Si programamos este pequeño script para otro lenguaje (Java o C por ejemplo) veremos que la variable "cont" es inaccesible fuera del bucle y tendremos un error, sin embargo en JavaScript nos muestra algo muy distinto (cont = 5). Para entenderlo mejor veamos que es un ámbito de variables en la programación.


   Cuando una variable es definida dentro de un bloque (for, while, if, etc) y es accesible solo dentro del mismo entonces decimos que el lenguaje maneja el ámbito de variables por bloques (block scope), sin embargo si la variable definida sigue siendo accesible fuera de dicho bloque (no función, sino bloque) entonces el lenguaje no maneja dicho ámbito. Ese es el caso de JavaScript, que tampoco maneja el ámbito contextual de las variables sino el ámbito de funciones (function scope).

Function Scope != Block Scope != Context Scope

   ¿A que me refiero con esto?, pues simple. Cada llamada a una función tiene un alcance y contexto asociada a la misma, el ámbito se basa en las funciones mientras que el contexto se basa en objetos. Entonces para estar claros en la definición:

- Block Scope: comprende el acceso a una variable cuando una función es invocada y es única por cada llamada.

- Context Scope: es el valor de la palabra reservada "this" el cual es una referencia al objeto que actualmente se posee en tiempo de ejecución.

   Entonces ¿donde queda el ámbito de la función?. Básicamente, la diferencia entre el ámbito de la función y del bloque es que, en un lenguaje que utiliza ámbito de la función, las variables declaradas dentro de una función son visibles en cualquier lugar dentro de la misma. Pero con el ámbito de bloque, la visibilidad de las variables se circunscribe a un bloque dado (if, while, for, etc) encerrada entre llaves (o el limitador del bloque, como ??>, END, etc).

   Ahora veamos un ejemplo sencillo donde podremos entender como manejar esto correctamente en JavaScript:
/*
 * Al definir la funcion de esta forma inicializamos
 * el objeto, si ya existe (digamos que otro script usa
 * el mismo nombre de variable) entonces lo instancia
 * haciendo la referencia al mismo objeto.
 */
var app = app || {};

app.contador = (function(){
 /*
  * las funciones declaradas dentro de este
  * bloque son inaccesibles desde fuera,
  * dando lugar a variables privadas internas
  *
  * Por ejemplo, si tratamos de acceder desde
  * fuera a la variable cont veremos que no
  * esta definida:
  * 
  * console.log(app.contador.cont); //-->undefined
  */

 var cont = 0;

 return {
  incrementar: function(){
   cont++;
  },
  sumar: function(i){
   cont = cont + i;
  },
  reducir: function(){
   cont--;
  },
  reiniciar: function(){
   cont = 0;
  },
  mostrar: function(){
   return cont;
  }
 }
})();

//Mostramos el valor (que debe ser 0)
alert("Contador: " + app.contador.mostrar());

//Aumentamos el valor
app.contador.incrementar();

//Sumamos 8
app.contador.sumar(8);

//A este punto el contador debe estar en 9
alert("Contador: " + app.contador.mostrar());

//Restamos 1
app.contador.reducir();

//Contador ahora es 8
alert("Contador: " + app.contador.mostrar());

//Reiniciamos
app.contador.reiniciar();

//Veremos que ahora esta en 0
alert("Contador: " + app.contador.mostrar());

Lamentablemente hay muchos usuarios en la red que han llegado al blog para escribir obscenidades, así que la moderación se hace necesaria. Recuerda utilizar un lenguaje correcto y espera a que sea aprobado.

Si necesitas publicar código haz click en "Conversión" para hacerlo legible.
ConversiónConversión EmoticonEmoticon