Avanzadojavascript
Closures y Scope
Comprende como funciona el scope lexico y como los closures capturan variables del entorno.
Que es el Scope
El scope (ambito) determina en que partes del codigo una variable es accesible. JavaScript tiene tres tipos:
- Global Scope: Accesible desde cualquier parte.
- Function Scope: Solo dentro de la funcion.
- Block Scope: Solo dentro del bloque
{} (con let y const).Que es un Closure
Un closure es una funcion que "recuerda" las variables del scope donde fue creada, incluso cuando se ejecuta fuera de ese scope.
javascript
1function crearContador() {
2 let count = 0;
3 return {
4 incrementar: () => ++count,
5 obtener: () => count,
6 resetear: () => { count = 0; }
7 };
8}
9
10const contador = crearContador();
11console.log(contador.incrementar()); // 1
12console.log(contador.incrementar()); // 2
13contador.resetear();
14console.log(contador.obtener()); // 0Funciones fabrica
Los closures son perfectos para crear funciones fabrica que generan funciones especializadas con configuracion predefinida.
javascript
1function crearMultiplicador(factor) {
2 return function(numero) {
3 return numero * factor;
4 };
5}
6
7const duplicar = crearMultiplicador(2);
8const triplicar = crearMultiplicador(3);
9
10console.log(duplicar(5)); // 10
11console.log(triplicar(5)); // 15El clasico bug del for loop
Uno de los bugs mas famosos involucraba closures dentro de loops con
var. La solucion moderna es simplemente usar let.javascript
1// Problema con var
2for (var i = 0; i < 3; i++) {
3 setTimeout(() => console.log(i), 100);
4}
5// Imprime: 3, 3, 3
6
7// Solucion con let
8for (let i = 0; i < 3; i++) {
9 setTimeout(() => console.log(i), 100);
10}
11// Imprime: 0, 1, 2Prueba lo aprendido
Escribe código JavaScript y ejecútalo directamente en el navegador.
Editor de Códigojavascript
1function crearContador() {
2 let count = 0;
3 return {
4 incrementar: () => ++count,
5 obtener: () => count,
6 resetear: () => { count = 0; }
7 };
8}
9
10const contador = crearContador();
11console.log(contador.incrementar()); // 1
12console.log(contador.incrementar()); // 2
13contador.resetear();
14console.log(contador.obtener()); // 0