Las variables globales pueden hacerse locales (privadas) con cierres.
Variables globales
Un function
puede acceder a todas las variables definidas dentro de la función, así:
Ejemplo
var a = 4;
devolver a * a;
}
Pruébalo tú mismo »
Pero un function
también puede acceder a variables definidas fuera de la función, así:
Ejemplo
función miFunción() {
devolver a * a;
}
Pruébalo tú mismo »
En el último ejemplo, a es una variable global.
En una página web, las variables globales pertenecen al objeto ventana.
Las variables globales pueden ser utilizadas (y modificadas) por todos los scripts de la página (y de la ventana).
En el primer ejemplo, a es una variable local.
Una variable local sólo se puede utilizar dentro de la función donde está definida. Está oculta a otras funciones y a otro código de scripting.
Las variables globales y locales con el mismo nombre son variables diferentes. Modificar una, no modifica la otra.
Las variables creadas sin palabra clave de declaración (var
let
, o const
) son siempre globales, aunque se creen dentro de una función.
Vida de las variables
Las variables globales viven hasta que se descarta la página, como cuando se navega a otra página o se cierra la ventana.
Las variables locales tienen una vida corta. Se crean cuando se invoca la función, y se borran cuando ésta termina.
Un dilema de contador
Supongamos que quieres usar una variable para contar algo, y quieres que este contador esté disponible para todas las funciones.
Podrías utilizar una variable global, y un function
para aumentar el contador:
Ejemplo
var contador = 0;
// Función para incrementar el contador
/función add() {
contador += 1;
}
// Llama a add() 3 veces
add();
add();
add();
// El contador debería ser ahora 3
Prueba tú mismo »
Hay un problema con la solución anterior: Cualquier código de la página puede cambiar el contador, sin llamar a add().
El contador debe ser local a la función add()
, para evitar que otro código lo cambie:
Ejemplo
var contador = 0;
// Función para incrementar el contador
función add() {
var contador = 0;
contador += 1;
}
// Llama a add() 3 veces
add();
add();
add();
/ El contador debería ser ahora 3. Pero es 0
Pruébalo tú mismo »
No ha funcionado porque mostramos el contador global en lugar del local.
Podemos eliminar el contador global y acceder al local dejando que la función lo devuelva:
Ejemplo
función add() {
var counter = 0;
counter += 1;
return counter;
}
// Llama a add() 3 veces
add();
add();
//El contador debería ser ahora 3. Pero es 1.
Pruébalo tú mismo »
No funcionó porque reiniciamos el contador local cada vez que llamamos a la función.
Una función interna de JavaScript puede resolver esto.
Funciones anidadas de JavaScript
Todas las funciones tienen acceso al ámbito global.
De hecho, en JavaScript, todas las funciones tienen acceso al ámbito «por encima» de ellas.
JavaScript soporta funciones anidadas. Las funciones anidadas tienen acceso al ámbito «por encima» de ellas.
En este ejemplo, la función interna plus()
tiene acceso a la variable counter
de la función padre:
Ejemplo
var counter = 0;
función plus() {counter += 1;}
plus();
return counter;
}
Pruébalo tú mismo »
Esto podría haber resuelto el dilema del contador, si pudiéramos llegar a la función plus()
desde fuera.
También necesitamos encontrar una forma de ejecutar counter = 0
sólo una vez.
Necesitamos un cierre.
Cierres de JavaScript
¿Recuerdas las funciones autoinvocables? Qué hace esta función?
Ejemplo
var counter = 0;
return function () {counter += 1; return counter}
}();
add();
add();
add();
// el contador es ahora 3
Pruébalo tú mismo »
Ejemplo explicado
La variable add
se asigna al valor de retorno de una función autoinvocable.
La función de autoinvocación sólo se ejecuta una vez. Pone el contador a cero (0), y devuelve una expresión de función.
De esta forma add se convierte en una función. La parte «maravillosa» es que puede acceder al contador en el ámbito padre.
Esto se llama un cierre de JavaScript. Hace posible que una función tenga variables «privadas».
El contador está protegido por el ámbito de la función anónima, y sólo puede ser cambiado usando la función add.
Un cierre es una función que tiene acceso al ámbito padre, incluso después de que la función padre se haya cerrado.