Definiendo conceptos - Closure y Scope en JavaScript
Qué es el Scope
El scope es el alcance de una variable, puede ser de dos tipos, global y local. Una variable cuyo scope es global se puede acceder desde cualquier parte del código, una local solo desde la función que la contiene. Ejemplo:
var a = 1;
function global() {
console.log(a);
}
global();
console.log(a);
En ese caso a
es una variable global ya que podemos acceder tanto fuera como
dentro de una función debido a haberla definido fuera de cualquier función.
function local() {
var a = 2;
console.log(a);
}
local();
console.log(a);
En este otro caso, la variable a
es local ya que la definimos dentro de la
función local()
, esto quiere decir que solo podemos acceder a ella dentro
dicha función, cuando ejecutamos local()
te muestra correctamente 2, mientras
que si haces console.log(a)
te va a dar error porque a no esta definida, para
el scope global esa variable no existe.
Esto te permite a vos decidir si querés una variable solo para X función o incluso si queres que una variable cambie su valor dentro de una función.
ECMAScript 2015/6
En Julio de 2015 se incorporó al estándar ECMAScript (el cual sirve de base para
JavaScript) nuevas formas de definir variables con un scope diferente usando la
palabra let
en vez de var
.
Este nuevo scope se lo conoce como scope de bloque. A diferencia del scope tradicional por función este scope esta limitado al bloque de código donde fue definida la variable.
Un bloque de código es el que se encuentra entre llaves o curly braces ({
y
}
), esto además de incluír las funciones incluye ciclos y condiciones, esto
quiere decir que una variable definida con let
puede solo existir en el scope
de un ciclo o una condición por ejemplo:
for (let i = 0; i < 10; i++) {
console.log(i);
}
console.log(i); // error
En este ejemplo la variable i
definida con let
solo exíste dentro del cíclo
por lo que el console.log
dentro del ciclo imprime correctamente el valor de
i
mientras que el console.log
fuera del ciclo daría un error porque la
variable i
no esta definida.
Qué es un Closure
Un closure es una función que tiene su propio contexto, esto quiere decir que las variables de la función padre funcionan dentro del closure, pero no se pueden acceder desde afuera. Ejemplo:
function padre() {
var a = 1;
function closure() {
console.log(a);
}
closure();
}
padre();
La función padre()
crea una variable local y una función closure()
. Esta
función interna es un closure y solo esta disponible dentro de padre()
.
Ahora considera este otro ejemplo:
function crearFuncion() {
var a = 1;
function closure() {
console.log(a);
}
return closure;
}
var miFuncion = crearFuncion();
miFuncion();
Este código hace lo mismo que el anterior. La diferencia es que la función
closure es regresada por crearFuncion()
sin haberse ejecutado. Normalmente una
variable local solo existe mientras se ejecuta dicha función y luego no es más
accesible, pero en este caso eso no se cumple. Eso es porque miFuncion()
se
convirtió en un closure, un objeto que combina una función y el contexto donde
fue creada, el contexto consiste en cualquier variable que estaba en su mismo
nivel de scope (las que pertenecen a crearFuncion
).
En este caso miFuncion()
incorpora la función closure()
y el valor 1
almacenado en a
cuando la función fue creada. Acá hay un ejemplo mejor:
function crearSuma(a) {
return funcion(b) {
return a + b
}
}
var sumar5 = crearSuma(5);
var sumar10 = crearSuma(10);
console.log(sumar5(15));
console.log(sumar10(15));
En este ejemplo la función crearSuma
recibe un argumento a
y retorna una
función. La función que retorna recibe un argumento b
y retorna la suma de a
y b
. Eso convierte a crearSuma()
en una función capaz de crear otras
funciones. En el ejemplo se usa crearSuma()
para crear dos funciones, la
primera para sumar 5 a una valor b
y la segunda suma 10.
Ejemplo más práctico:
function changeSize(a) {
return function() {
document.body.style.fontSize = a + "px";
};
}
var size12 = changeSize(12);
var size14 = changeSize(14);
var size16 = changeSize(16);
Estas tres funciones size12
, size14
y size16
permiten cambiar el tamaño de
fuente al valor indicado al momento de crear el closure. Luego podemos
asignarlas al evento click de algún botón y permitir de esta forma que se cambie
facilmente el tamaño de fuente de nuestro sitio.