Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Ámbito léxico en closures

7/12
Recursos

Aportes 117

Preguntas 29

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

“Mágico”

Habría sido bueno que el profesor hubiera dedicado tiempo a explicar la mecánica del closure. Por qué es que la variable es capaz de mostrar un resultado diferente al que si ejecutamos la función directamente. Cuál es el papel de la memoria interna en este comportamiento, etc. Ahora está todo muy "mágico"
Los estudiantes han aportado valiosos comentarios en este sentido, pero son estudiantes como yo. No es lo mismo que te lo explique el profesor.
Es mi opinión.

Si te llegaste a preguntar ¿Por qué si le mandamos como parámetro inicial 1, al momento de llamar el closure por primera vez me imprime 1 si lo estoy incrementando?
Bueno, pues yo te lo explico.

Si vemos la estructura de la función

const buildCount = (i)=>{
    let count = i;
    const displayCount = () =>{
        console.log(count++);
    }
    return displayCount;
};

Podemos notar que el console.log() está de de la siguiente manera

console.log(count++);

Y como ves, aparece count++, lo que quiere decir que estamos incrementando en 1 el valor de count, pero de la manera que está escrita, primero va a imprimir el count con el valor antes de incrementarlo
Esto se debe a que count++ es lo equivalente a decir count = count + 1 pero el momento en el que se hará ese incremento, está dado por la posición del ++, en éste caso, se hará después.
Si quisieramos que se muestre el valor de count después de hacerle el incremento, podríamos hacer ésto:

count++;
console.log(count);

O, de una manera más elegante, y aprendiendo como funciona el ++, así:

console.log(++count);

Espero haberte ayudado y suerte en el camino a la maestría 😉

El ámbito léxico es cuando las funciones se ejecutan utilizando la cadena del alcance donde estaban vigente en su momento.

Esto significa que podemos acceder al valor “count” dentro de la función porque es el alcance donde está asignado.

Podemos tener varias formas de manejar la constante “buildCount”, significa que la podemos asignar a myCount y myOtherCount. Trabajaremos con el scope(alcance) que tiene esta variable, poder ejecutarla y empezar a contar desde donde necesitemos.

const buildCount = i => {
  let count = i;
  const displayCount = () => {
    console.log(count++);
  };
  return displayCount;
};

const myCount = buildCount(1);
myCount(); // 1
myCount(); // 2
myCount(); // 3

const myOtherCount = buildCount(10);
myOtherCount(); // 10
myOtherCount(); // 11

Que efecto tan interesante

Ejemplo 1 - como lo hizo el teacher

const moneyCounter = (i) => {
  let count = i;
  const counts = () => {
    console.log(`valor $${count++}`);
  };
  return counts;
};

const counter = moneyCounter(10)
counter() // valor 10
counter() // valor 11

Ejemplo 2 - la diferencia es que hago el incremento antes del console.log que muestra el valor

const moneyCounter = (i) => {
  let count = i;
  const counts = () => {
    count ++;
    console.log(`valor $${count}`);
  };
  return counts;
};

const counter = moneyCounter(10)
counter() // valor 11
counter() // valor12

Al parecer en un console.log no puedo usar el operador ++, fíjense en el siguiente ejemplo:

let suma2 = 0
console.log(suma2++) // 0

let suma = 0
suma++
console.log(suma) // 1

Pero si uso el operador +=1 si jala.

let suma2 = 0
console.log(suma2+=1) // 1

let suma = 0
suma++
console.log(suma) // 1

Espero les de la misma curiosidad que a mi ajajaj

Aprender closures es una de las cosas más valiosas en JavaScript. Saber usarlo marca unagran diferencia

Este concepto de Closures me tomo tiempo entenderlo, pero insistí tanto que termine desglosando los conceptos y siento que ahora si lo entiendo. Lo logre primero con esta lectura (https://gustavodohara.com/blogangular/execution-context-contexto-ejecucion-javascript/) y lo complemente con este video (https://youtu.be/JXG_gQ0OF74). Ojala a alguien le sirva ese paso a paso porque fue lo que al final me ayudo.

Yo me imagino que todos ya entendieron closures y quizás no les haga falta una explicación adicional. A mi me costo verlo claramente y tuve que ir a buscar mas documentación hasta que vi un video que me lo aclaró todo. Estos tips van dirigidos a los que aun no lo ven tan claro. Sigan la explicación desde el punto 1, punto por punto.

  1. Este será el código de ejemplo para explicar

El closure es una 1era función que contiene variables locales y una de esas variables es una 2da función

const moneyBox = (i) => {		 		//1era Función
    var saveCoins = i					//1era variable
    	const sumaCoins = (coins) => {  		//2da variable y  función interna 
       		 saveCoins+= coins 
       		 console.log(`MoneyBox: ${saveCoins}`)
          }
	
	return sumaCoins
}

let myMoneyBox = moneyBox(10)
myMoneyBox(5)
myMoneyBox(40)
  1. Si se fijan, la variable 2 ( la 2da función) es retornada sin ejecutarse, mediante la línea de código ‘return sumaCoinst’ pues no tiene los paréntesis , esto es clave y significa que lo que se retorna no es un valor sino el esqueleto de esa 2da función, es decir, el código de la función como tal junto con las variables del ámbito donde se encuentra y los valores de esas variables como

gráficamente seria como si esto estuviera pasando esto:

  return  
	const sumaCoins = (coins) => {  		 
       		 saveCoins+= coins 
       		 console.log(`MoneyBox: ${saveCoins}`)
          }

  1. Este esqueleto (o la función en código puro) es almacenada en myMoneyBox y es como si estuviera pasando esto:
let myMoneBox = 
	const sumaCoins = (coins) => {  		 
       		 saveCoins+= coins 
       		 console.log(`MoneyBox: ${saveCoins}`)
          }	
  1. Luego cuando se ejecuta la línea de código ‘myMoneyBox(5)’ literalmente estamos ejecutando myMoneybox que ahora contiene a la función ‘sumaCoins’ y entonces es como si esto estuviera pasando:
let myMoneBox = 
	const sumaCoins = (5) => {  		 
       		 saveCoins+= coins 		//aqui saveCoins trae el valor de 10 con el cual fue retornado desde la 1era funcion 'moneyBox'
								//y coins recibe 5 y se realiza la suma  
       		 console.log(`MoneyBox: ${saveCoins}`)
          }	

Es clave recordar que la variable ‘saveCoins’ trae el valor de 10 ya que cuando la función ‘sumaCoins’ fue retornada ella se trae tambien las variables del ámbito léxico

Entonces se ejecuta el console.log: MoneyBox: 15

  1. Cuando se ejecuta la línea de código ‘myMoneyBox(40)’ se llama nuevamente a myMoneyBox y esto seria como si estio estuviera pasando:
let myMoneBox = 
	const sumaCoins = (40) => {  		 
       		 saveCoins+= coins 		//aqui saveCoins tiene el valor de 15m de cuando se ejecutó myMoneyBox(5)
								//y coins recibe ahora 40 y se realiza la suma 15 + 40  
       		 console.log(`MoneyBox: ${saveCoins}`)
          }

Entonces se ejecuta el console.log: MoneyBox: 55

No se si lo puse mas complicado pero espero les ayude

La verdad es un tema un poco más complejo de lo que se pinta en este video, por lo cual como no lo entendi mucho me pongo en la tarea de buscar más info y más referencias y es por eso que me gustaría mucho que vieran este video. Yo se que muchos lo conocen.
La cocina del codigo - Closures

Ámbito léxico.- Se refiere a que el lenguaje sabe de que scope tiene cada variable y cuál variable debe de utilizar por ejemplo si tiene el mismo nombre sabe que variable manipular.

La forma de mezclar los closures con el ámbito léxico es que cada que se llama la función con el closure sus valores no se mezclan es decir cada llamada solo manipula en ambito léxico que el corresponde.

const billCount = (i) => {
    let count = i;
    const displayCount = () => {
        console.log(count++)
    }
    return displayCount
}

const myCount= billCount(1)
const myOtherCount= billCount(10)

myCount()
myOtherCount()
myCount()
myOtherCount()
myCount()
myOtherCount()

Es necesario mas practica para entender bien el funcionamiento de los closures.

//el ambito lexico son las funciones que se ejecutan ulizando
//la cadena del alcance donde estaba vijente en en su momento
//es decir que se tiene el valor de count que esta declarado en la funcion principal
//pero esta accecible dentro de siguiente funcion

const buildCount = (i) => {
    let count = i;
    const displayCount = () => {
        console.log(count++);
    };
    return displayCount;
}

const myCount = buildCount(1);
myCount();
myCount();
myCount();

//aqui tenemos un nuevo closure, un nuevo alcance, un nuevo ambito
const myOtherCount = buildCount(10);
myOtherCount();
myOtherCount();

Lo que vi es que el count++ primero imprime el count y luego se suma el 1.

**Si quieres hacer que el closure recuerde cualquier resultado, pasa el argumento también a la segunda función:
**
Ejemplo


const llevaLaCuenta = (numero) => {
  const cuenta = 0;
  const aumentarcuenta = (numero) => {
    cuenta+=numero
    return console.log(cuenta);
  }
  return aumentarcuenta
}

let llevameLaCuenta = llevaLaCuenta()

llevameLaCuenta(3)
llevameLaCuenta(4)
llevameLaCuenta(5)

// IMPRIME   3  7   12

Primero crea el contexto de ejecución inicial, Global

Es un objeto que tienen los contextos de ejecucion donde se almacenan los nombres de las variables que existen dentro de una funcion y los valores actuales que tienen. Tienen clave y valor

La clave son los nombres de las variables o parametros

Los valores son los valores actuales

Cada entorno lexico tiene un puntero a su entorno lexico exterior

  1. Fase de creación

    Se inicializa el registro, se coloca el puntero de la proxima linea, el objeto global, window, this

  2. Fase de ejecución

    JS ejecuta sentencia por sentencia

Existen 3 identificadores de variables

  1. El nombre de la funcion es un identificador y se carga en memoria cuando se crea el contexto de ejecución, cada vez que Js crea una nueva funcion en memoria esta funcion la vincula al entorno donde la creo, el entorno lexico global

Hoisting es darle valores iniciales a las variables y cargar las funciones en memoria

Una forma de utilizar closures, es para crear variables privadas.

// declaracion de la function 
const newCount = (count = 0) => {
    return {
        increment: () => console.log(++count), 
        decrement: () => console.log(--count),
        get: () => console.log(count)
    }
}
// creacion de un new contador
let contador1 = newCount()

contador1.increment()
contador1.increment()
contador1.increment()
contador1.decrement()
contador1.decrement()
contador1.get()

La palabra léxico hace referencia al hecho de que el ámbito léxico se basa en el lugar donde una variable fue declarada para determinar dónde esta variable estará disponible. Las funciones anidadas tienen acceso a las variables declaradas en su ámbito exterior.
By: https://mzl.la/3eBJimc

Si quieren poner a prueba su lógica con javascript y practicarlo hasta perfeccionarlo. Les recomiendo el programa de Henry https://www.soyhenry.com/ y hasta conseguir trabajo.
Lo estoy haciendo en este momento y es muy intenso. Tener buenas bases de JS y conceptos para entender a fondo JS con los de este curso ayudan bastante.

Resumen de clousre: una función adentro la otra. Fin.

Un video que les solucionara la vida
https://www.youtube.com/watch?v=JXG_gQ0OF74&t=1s

Código de la clase

const buildCount = i => {
  let count = i;
  const displayCount = () => {
    console.log(count++);
  };
  return displayCount;
};

const myCount = buildCount(1);
myCount(); //1
myCount(); //2
myCount(); //3

console.log("---------------");
const myOtherCount = buildCount(10);
myOtherCount(); //10
myOtherCount(); //11

Les recomiendo ampliamente que vean este video donde se explican las Clausuras, con una explicación completa y detallada de como funciona la pila de tareas de JS, entre otros aspectos importantes.

https://www.youtube.com/watch?v=JXG_gQ0OF74&ab_channel=LaCocinadelCódigo

Hay que tener el cuenta el funcionamiento del operador de incremento (++)
Cuando se coloca despues de la variable

let count = 0
console.log(count++)      // Imprime 0

Lo que sucede es que la variable primero devuelve el valor (0 en este caso) y luego hace el incremento.

let count = 0
console.log(count++)      // Imprime 0
console.log(count)        // Imprime 1

Si queremos que suceda lo contrario, es decir, que primero haga el incremento y luego devuelva el valor solo hay que ponerlo antes de la variable:

let count = 0
console.log(++count)      // Imprime 1

Pasa lo mismo con el operador de decremento.

Entorno Léxico
Es un objeto que tiene los contextos de ejecución donde almacenan los nombres de las variables que existen dentro de una función y los valores actuales que tiene.

Me gustó esta clase, el profe sabe muchísimo y se aprende bastante con él; estaría bien si como feedback se le recomienda una mejora de la pronunciación del inglés? 😬🙂

Ámbito léxico
El ámbito léxico es el entorno del closure, es decir las variables y funciones en su scope al momento de generarse nuestro closure, es decir con los valores de ese momento

Cada vez que se ejecuta una función en JavaScript, se crea un nuevo contexto de ejecución con un nuevo entorno léxico. “La Cocina del Código - Sachiza Lifszyc”.

Para que lo puedan entender mejor los invito a probar el codigo en a siguiente paina, la cual indica paso a paso lo que esta sucediendo.

https://pythontutor.com
dentro de la pagina ingresana javascript tutor

le dan click en visualize ejecution

y en la parte inferior izquierda navegan por los pasos.

En lo personal pude entender mejor lo que estaba sucediendo.

Si despues de todo lo que mis compañeros de clase han explicado aun tienes dudas, espero que esto lo haga mas simple, vamos a desmenusar el código que estamos viendo en el closure de la clase:

const lexical = (i)=>{
    var counter = 1;

    const inc = ()=>{
        console.log(counter++)
    }

    return inc;
}

const incrementer = lexical(1);

incrementer()
incrementer()
incrementer()

lo primero que hay que entender es que al momento de llamar a nuestro closure tenemos que asignar un valor inicial, es decir, un valor a i de la siguiente manera:


const incrementer = lexical(1);

Lo siguiente que hay que entender es que el código:

console.log(counter++)

Se le conoce en muchos lados como operador avanzado, el cual tiene 2 metodos de implementacion: pre y post operacion; esto es, se puede operar a la variable antes o despues de utilizarla; en el ejemplo lo que se hace es que primero se utiliza el valor que counter tiene declarado previamente y despues acualizamos su valor. en el ejemplo ocurre algo como lo siguiente:

  1. asignamos el valor de 1 como inicial
  2. mostramos el valor 1 e incrementamos en uno el valor de counter, dejando counter = 2 despues de imprimirlo
  3. mostramos el valor de 2 e incrementamos en uno el valor de counter, dejando counter = 3 despues de imprimirlo
  4. mostramos el valor de 3 e incrementamos el valor de counter , dejando counter = 4 despues de imprimirlo

si aun tienes dudas sobre ese tema, ejecuta el siguiente codigo y analizalo con lo anterior:

const lexical = (i)=>{
    var counter = 1;

    const inc = ()=>{
        console.log(counter++)
        console.log(`valor despues de ++ ${counter}`)
    }

    return inc;
}

const incrementer = lexical(1);

incrementer()
incrementer()
incrementer()

Me costó un rato entenderlo pero ahora, creo que puedo ayudarles con esto.

const buildCount = (i) => {
    let count = i;
    const displayCount = () => {
        console.log(count++)
    }
    return displayCount;
}

Primero entendamos lo que hace esto.
Tenemos una función con un parametro (i)
y adentro tiene una variable count que es igual al valor de (i), y adentro una función que suma 1 a nuestra variable count, y al final retonornamos la función que tenemos adentro

let anotherFunction = buildCount(10);
anotherFunction();
anotherFunction();
anotherFunction();

Ahora entendamos esta parte, declaramos una función que contiene una función y le pasamos el argumento de 10.
Pero ¿Qué esta pasando exactamente?
Lo que sucede es que invocamos nuestra función buildCount con un argumento de 10, lo que quiere decir que nuestra función ejecuto su codigo, lo que se traduce:
count es igual al argumento que pasamos, ahora count vale 10, luego ve una función que hasta ahora no hace nada, y al final nos retorna esa función, TODA LA FUNCIÓN, entonces nuestra variable es igual a la función retornada, nuestra variable es displayCount.
Ahora esta se ejecuta cuando hacemos anotherFunction();
¿qué es lo que hace?
Se invoco esta función y le que tiene que imprimir y sumar un variable count, qué recordemos vale 10 en este caso,
la lee imprime un 10 y luego de imprimir, añade 1 nuestra variable count, ahora vale 11.

Y en nuestra segunda repetición, volvemos a ejecutar nuestra funcion displayCount con count valiendo 11, imprime 11 y luego le añade 1.
Y esto amigos es básicamente lo que he entendo acerca de los closures, pero antes que todo pueden que se esten preguntando ¿Por qué no imprime el valor sumado, si no el antes de sumar?
Para eso entendamos el operador ++, este puede colocarse al principio o al final, he ahí la diferencia.
veamos esto:

let x = 3;
y = x++;

// y = 3
// x = 4

Esto es cuando colocamos despues de lo que queremos sumar se conoce como Postfix increment
Y funciona qué el valor incrementa, pero nos retorna el valor antes de aumentar, por eso con count nuestro ejemplo anterior nos retorna 10, y se suma despues valiendo 11.
Si quisieramos que nos retorne ya el valor sumado solo debemos cambiar la posicion del operador

let a = 2;
b = ++a;

// a = 3
// b = 3

Espero que les haya servido!

Para los que tienen dudas de por que el contador empieza desde el numero que le ingresaste(en el ejemplo el 10), es por que cuando hacemos este proceso console.log(count++); le estamos diciendo que primero imprima y luego incremente en uno contrario a console.log(++count); en donde primero incrementa y luego imprime.

//A continuación daremos más ejemplos de como utilizar un closure;
const buildCount = (i) => {
    //Esta es nuestra variable que va a almacenar los cambios
    let count = i;

    //Con esta funcion incrementamos en 1 despues de imprimir 
    const displayCount = () => {
        console.log(count++);
    }

    //Retornamos la funcion que se mandara a llamar desde el ScopeGlobal
    return displayCount;
}

//Le pasamos el valor desde el cual va a empezar el contador
let myCount = buildCount(10);

myCount(); //Aqui hace regerencia a displayCount() que va a incrementar en 1 el valor
myCount();
myCount();```
/* resumen de closure
  1. Declara las variables que quieres que tengan memoria
  2. Declara el closure: funcion dentro de funcion: funcion manejadora de memoria
  3. Retorna la funcion manejadora de memoria
  4. Hereda tu funcion a otras variables
  5. Ejecutala varias veces y ve como recuerda su valor
*/
const buildCount = (i) => {
  let count = i; // 1
  const displayCount = () => { // 2
    console.log(count++)
  }
  return displayCount; // 3
}

const myCount = buildCount(2); // 4
myCount() // 5
myCount()
myCount()
myCount()

Cada vez me queda más claro que son los closure y el ambito léxico.
Este video me ayudo mucho a entender de que trata a más detalle.

Recomiendo investigar cuál es la diferencia entre “count++” y “++count” para que vean por qué salen esos numeros 👀

count++

vs

++count

probablemente como yo se preguntaron porque aunque el parámetro sea 10. Al “contar” por primera vez, la consola imprime 10.
Bueno, esto ocurre porque js tiene esas dos formas de sumar un valor. La primera retorna el valor y luego hace la suma. Mientras que el segundo, realiza la adición y luego retorna ese nuevo valor

Closures

Ámbito léxico : es cuando las funciones se ejecutan utilizando la cadena del alcance donde estaba vigente en el momento de su creación accediendo a ese espacio de memoria y poder tomar el valor de la variable dentro de la función.

// Lexical ambit class code

const buildCount = (i) => {
  let count = i;
  const displayCount = () => {
    // count++;
    console.log(count++);
  };

  return displayCount;
};

const myCount = buildCount(1);
myCount();
myCount();
myCount();

const myOtherCount = buildCount(10);
myOtherCount();
myOtherCount();
myOtherCount();

Repositorio 🐙

const buildCount = (i) => {
  let count = i;
  const displayCount = () => {
    console.log(count++);
  };

  return displayCount;
};

const myCount = buildCount(1); 
// Lo que sucede en esta línea de código es que se crea una variable con el valor número 1. Este valor de la variable vive en buildCount(), solo que ahora está siendo guardado en myCount. Sin embargo, buildCount() tiene una función dentro que retorna un console.log(count++). Encontes quedaría myCount = () => { console.log(count++) } y al nosotros darle como valor 1, este arrojará 1, porque eso hace la función. Y cada vez que inicializamos la constante myCount() el valor irá en aumento gracias a la función displayCount() -> Si count es i, suma 1.
myCount();
myCount();
myCount();

const myOtherCount = buildCount(10);
myOtherCount();
myOtherCount();
const buildCount =(i)=>{//Nuestra funcion recibe un valor i
  let count =i;
  const displayCount=()=>{
    console.log(count++);//Actualizamos el valor de count en +1
  }
  return displayCount;//Retornamos el nuevo valor de count
}

const myCount=buildCount(8);
/*El valor que pasamos como i va ser nuestra base que aumenta en 1*/ 
myCount();//8
myCount();//8+1=9
myCount();//9+1=10


No me quedaba muy claro porque se mostraba en consola los resultados 1, 2 y 3 para myCount(). 10 y 11 para myOtherCount(). Gracias a los comentarios de la clase comprendí que era por el motivo de que con el count++ del console.log se le estaba incrementando en 1 el valor del parámetro.
Para dejar el ejercicio como el de la clase anterior, en el que iba recordando el valor e incrementándolo con el nuevo valor hice lo siguiente:

const buildCount = i => {
  let count = 0;
  const displayCount = () => {
    count += i ;
    console.log(`Total $${count}`);
  }
  return displayCount;
}

const myCount = buildCount(2)
myCount() // 2
myCount() // 4
myCount() // 6

const otherCount = buildCount(10)
otherCount() // 10
otherCount() // 20

Por tanto, me quedo con que el ámbito léxico de los closure permite acceder a los valores de la función superior a esta, por ejemplo acá en el ejercicio estoy accediendo a i dentro de displayCount.

Otra cosita que leí mientras intentaba comprender mejor los closure, es que el Global Object que vendría siendo window también es un Scope y creamos closure con más frecuencia de lo que pensábamos.
Por ejemplo al hacer lo siguiente, también estamos trabajando con los closure:

const msg = "Hola mundo";

function callMsg() {
	console.log(msg)
}

callMsg() // Hola mundo

Gracias a todos por sus aportes, de verdad son de mucha ayuda. Saludos y espero que haya sido de ayuda.

Mas interesante seguir con el ejemplo de la alcancía.

function crearAlcancia (inicial=0) {
	let ahorros = inicial
	console.log(`\nFelicidades, creaste una nueva alcancía con $${ahorros}\n`)
	function agregarMoneda(moneda) {
		console.log(`Ingresaste: $${moneda}`)
		ahorros += moneda
		console.log(`Total ahorrado: ${ahorros}`)
	}
	return agregarMoneda
}

let alcanciaDeJuan = crearAlcancia(10000)
alcanciaDeJuan(500) // 10500
alcanciaDeJuan(500)	// 11000
alcanciaDeJuan(500)	// 11500

let alcanciaDeAna = crearAlcancia()
alcanciaDeAna(200)	// 200
alcanciaDeAna(200)	// 400
alcanciaDeAna(500)	// 900 ```

Aquí lo importante a recalcar, es el retorno de la función displayCount, en ella esta el ámbito lexico actual de count, es por ello que, al llamarlo, suma 1, pero también es debido a que usamos el iterador ++, recordemos que ++ devuelve el valor inicial de la variable o expresión y después devuelve el valor de la variable o expresión mas 1.
Es este ejemplo:
let a = 1; let b = a++; console.log(b);
¿Qué valor se muestra en la consola?

Un Closure es un tipo especial de objeto que combina dos cosas: una función y el entorno en donde se creó dicha función. Por lo tanto para cada nuevo clojure que creemos, vamos a tener un entorno diferente y los valores de las variables en cada clojure serán independientes.

Si alguno esta algo perdido con esta explicacion en MDN
hay una explicacion mas grafica, que explica de una manera mas simplificada y visual como funcionan los closures

Los closure son similares a cuando creamos una instancia de un objeto en otros lenguajes de programación. Podemos crear las instancias que necesitemos con argumentos específicos para cada instancia.

El tema es bastante interesante, estoy interesado en conocer cuáles pueden ser los posibles casos de usos / áreas de aprovechamiento para la implementación de esta funcionalidad del lenguaje! 🤓

Comparto con varios compañeros, no siento que vaya entendiendo a profundidad, ya que creo que es muy superficial la explicación, espero que los siguiente curso de la ruta de desarrollo web pueda tener una explicación mas profunda sobre estos temas.

Por que al ejecutar simplemente
buildCount(10);
no me aparece nada en consola si le estoy entregando el parámetro para ser ejecutada :'0 Mi no entender

const buildSum = (n) => {
	return sum(n + n);
	function sum(a, b) {
		return a + b
	}
}

buildSum(2) // 4

en pocas palabras el ambito lexico es la facultad que tiene una funcion “interior” (que esta dentro de otra funcion) a acceder o modificar variables de una funcion que la contiene, por ello la importancia de entender los scopes antes de los clousures

me aburrí escribiendo myCount() así que decidí ponerla en un loop
es divertido mesclar lo aprendido en otros cursos

const buildCount = (i) =>{
    let count = i
    const displayCount = () => {
        console.log(count++)
    }
    return(displayCount)
}

const myCount = buildCount(1)

const conteo = () =>{
    for(let i = 0; i<100; i++){
        myCount(i)
    }
    return(myCount)
}

conteo(100)```

Aquí acabo de probar mi teoría, de que el closure no guarda el resultado de la variable en money sino en el contenedor const que le pongamos, por ende podemos reutilizar los closure en diferentes casi así como se haría con una function normal.

const MoneyBox = () => {
    let money = 0;
    const addMoney = (coins) =>{
        money += coins;
        console.log('MY money is ' + money)
    } 
    return addMoney
}

const Numerador1 = MoneyBox();
Numerador1 (10); // 10
Numerador1 (10); // 20
Numerador1 (10); // 30

const Numerador2 = MoneyBox();
Numerador2(20); // 20
Numerador2(20); // 40
Numerador2(20); // 60

Palabra del ingles TYPO /ˈtaɪ.poʊ/
…a small mistake in a text made when it was typed or printed

https://dictionary.cambridge.org/us/dictionary/english/typo

El ambito lexico son las funciones que se ejecutan utilizando la cadena del alcance donde estaba vigente en su momento. Es donde gracias a su alcance de la primer variable declarada, podemos modificarla.

const buildCount = (i) =>{
    let count = i;
    const displayCount = () => {
        console.log(count++);
    };
    return displayCount;
}

const myCount = buildCount(1);
myCount();
myCount();
myCount();
myCount();

Me pueden explicar una cosa, porque cuando inicializa la function

const myCount = buildCount(1);

//para mi deberia devolver ahi nomas 2

no se ejecuta la misma? nunca use así una function asi que si me lo explican se los agradecería

Existe algo que se llama referenciación. básicamente es usar variable para guardar un función (al llamar la variable hacemos “referencia” a la función).

const referencia = funcionX()

La función no solo se almacena en esa variable si no que la variable pasa a ser una función también y se puede invocar como tal (esto tiene varios usos en react).

referencia();

Con esto definido, pregunta, que pasa si le paso parámetros a la referenciación??

referencia( parámetros = "escribir algo aquí") 

La respuesta: Esos valores estarán también disponible para la función que fue referenciada dentro de la variable, incluso podría pasar valores dentro de la función referenciada al tiempo dentro de dicha variable para hacer casos “únicos”.

function funcionX (destinatario) {
   return function (saludo) {
        console.log(`${saludo} ${destinatario}`);
    };
};

const referencia_1 = funcionX('MUNDO!');
referencia_1('HOLA!');

const referencia_2 = funcionX('PLATZI');
referencia_2('HOLA!');

Que podemos hacer? aun no estoy seguro, en mi caso lo uso para no reescrbir funciones con diferentes eventos, tambien para que la invocacion sea mas sencilla y para aprobechar el scope de cada una metiendoles valores a la referenciacion jejeje

Debe haber mucho mas pero tambien ando aprendiendo 😉

Les recomiendo 100% este articulo, es un poco largo de leer pero créanme, les ayudara muchísimo a entender como funciona los closures

The closure is a function that accesses its lexical scope even executed outside of its lexical scope.

https://dmitripavlutin.com/simple-explanation-of-javascript-closures/

https://youtu.be/xa8lhVwQBw4 no entendía bien los closures hasta que vi ese vídeo y los vi como las clases en Java o otros lenguajes de programación

Recuerden que a una variable se le puede aplicar el operador incremento ++, tanto detras como delante de la variable.

La diferencia radica en que si lo colocas detras de la variable (++ variable) primero lo aumenta y luego se ejecuta, caso contrario si lo colocas por delante (variable ++) primero ejecuta lo que tiene que hacer y luego lo aumenta.

Es por esto que se imprime 1 2 3 y 10 11. Ya que primero imprimo luego aumento. Espero les sirva 😃

Resumen de la clase

const buildCount = (i) => {
    let count = i;
    // Funcion interna
    const displayCount = () => {
        // Se realiza un autoincrement
        console.log(count++);
    }
    return displayCount;
}

const myCount = buildCount(1);
myCount();
myCount();
myCount();

const myOtherCount = buildCount(11);
myOtherCount();
myOtherCount();
myOtherCount();

Buen dia campeon o campeona. Si asi es,

++count

si de entrada estamos pasando un valor por defecto, por logica el siguiente valor es el numero consecutivo del valor establecido.

const buildCount = (i) => {
  let count = i;

  return displayCount = () => {
    console.log(++count);
  }
}

let myCount = buildCount(0);
myCount() //1
myCount() //2
myCount() //3

//nuevo alcance o ambito lexico
let myAnotherCount = buildCount(20);
myAnotherCount() //21
myAnotherCount() //22
myAnotherCount() //23

Contexto de ejecución

El contexto de ejecución de una función es un registro de la información necesaria para que el motor de JavaScript pueda ejecutar dicha función.

Este registro pasa a formar parte del Call Stack de JavaScript.

Dentro de ésta registro está incluido el entorno léxico.
.

Entorno léxico

Es un objeto que forma parte del entorno de ejecución de una función y en el que se almacena, de forma dinámica, los nombres de las variables accedidas por la función así como sus valores.

Esta clase, finalizando el curso nos enseña cómo podemos hacer debugging.

Puede ser útil para entender mejor el comportamiento en el ejercicio de esta clase.

https://platzi.com/clases/1807-scope/26314-debugging/

Como todo en la vida nada se aprende con un video de 5 minutos, por eso es bueno profundizar por cuenta propia en los temas vistos y no hay mejor fuente que los blogs y documentación oficial:

En este video aprenden en 30min todo lo que no se ve en este curso, no me convence la forma de enseñar de este profesor.
https://www.youtube.com/watch?v=JXG_gQ0OF74&ab_channel=LaCocinadelCódigo

Ahora sí está clarísimo!!!

Si quieren profundizar más en el tema les recomiendo ver este video del profesor Sacha Closures

si no entendieron
vengo del futuro vayan a la clase 10 y aprenderan a hacer experimentos cuantos les sea necesario para CASI no tener que preguntar

Para los que no entendieron bien lo del count++

let count = 10;

console.log(count++) // 10
console.log(count++) // 11

Esto pasa porque cuando usamos count++, primero se nos imprime el número y luego se incrementa. Es decir, en el último console.log que hicimos, se nos imprimió el 11 y luego se incrementó la variable, por lo que ahora la variable vale 12:

console.log(count) //12

Una clausura o closure es una función que guarda referencias del estado adyacente (ámbito léxico). En otras palabras, una clausura permite acceder al ámbito de una función exterior desde una función interior. En JavaScript, las clausuras se crean cada vez que una función es creada.

Para quien no haya llagado a entender este y el concepto de “Closures” en general, recomiendo este blogpost donde se explica un caso parecido de manera mas detallada.

He revisado documentación externa para complementar. Me gusto mucho la de FreeCodeCamp, explican muy bien los dos conceptos.

“Cuando entiendas completamente las cláusulas, es posible que sientas lo que sintió Neo cuando vio la Matriz. ¡Verás nuevas posibilidades de código y te darás cuenta de que estuvieron ahí todo el tiempo!”

https://www.freecodecamp.org/espanol/news/tutorial-de-clausulas-de-javascript-como-funcionan-los-clausulas-y-el-ambito-lexico-en-js/

aqui le comparto una documentacion completa sobre los closure https://es.javascript.info/closure espero que le sea de utilidad.

les recomiendo este video donde a mi parecer explican mejor que aquí https://www.youtube.com/watch?v=JXG_gQ0OF74&t=937s

QUE EXCELENTE CLASE ES ESTA!!!
Dijo nadie nunca.

a ver les explico por que parece que no esta bien explicado cada vez que se ejecuta una variable se crea un entorno lexico en este entorno léxico se almacena todo lo necesario para ejecutar esa función por eso cada vez que ejecuta la funcion el contador aumenta por que en su entorno léxico el primer valor es uno luego se vuelve a ejecutar y este valor aumenta a 2 eso quiere decir que en su entorno léxico ya no vale 1 ahora vale 2 al hacer la segunda ejecución bajo la constante myOtherCount se crea otro entorno léxico totalmente diferente para esa ejecución

La verdad hay clases donde el profesor explica muy mal las cosas y no se entiende nada

Hay algo interesante que no me había dado cuenta con los parámetros.

Cuando le pasamos el parámetro al momento de declarar la función myCount, este se va a utilizar el ámbito exterior. En cambio si se lo pasamos a los que llamamos al final, es decir en función myCount, este parámetro se usa en la función interiror, es decir en displayCount.
Por ejemplo aquí:

const buildCount = (i) => {
    let count = i;
    const displayCount = (test) => {
        console.log(count++);
        console.log(test)
    }
    return displayCount;
}

const myCount = buildCount(1);

myCount('prueba');
myCount('de');
myCount('texto');

En const myCount = buildCount le estamos pasando el parámetro 1 que se va a utilizar para el tema de contador.
En myCount al final, le estamos pasando parámetros como texto de prueba que se van a utilizar en la función displayCount.
Este sería el resultado:

[Running] node ".../src/closure/tempCodeRunnerFile.js"
1
prueba
2
de
3
texto

[Done] exited with code=0 in 0.317 seconds

Y lo otro es que no solo se le puede pasar un valor. Puede ser mas de uno.
Por ejemplo en este caso diferencio las alcancías:

const moneyBox = () => {
    let saveCoins = 0;
    return countCoins = (coins, box) => {
        saveCoins += coins;
        console.log(`My money ${box}: $${saveCoins}`);
    }
}

let myMoneyBox = moneyBox();
let anotherMoneyBox = moneyBox();

anotherMoneyBox(7, "Another");
myMoneyBox(34, "My");
anotherMoneyBox(23, "Another");
myMoneyBox(9, "My");
anotherMoneyBox(12, "Another");
myMoneyBox(10, "My");

Nótese que creo dos alcancías pero para diferenciarlas le ingreso otro parámetro para darle un nombre. El resultado seria algo asi:

[Running] node ".../src/closure/tempCodeRunnerFile.js"
My money Another: $7
My money My: $34
My money Another: $30
My money My: $43
My money Another: $42
My money My: $53

[Done] exited with code=0 in 0.336 seconds

Excelente la explicación, pero creo que los ejemplos serían muchos mas certeros si explicaran con casos de uso reales que nos permitan de forma mas fácil ver su aplicación en un proyecto real.

Me pasa que al ver ejemplos tan básicos como de un contador mi cerebro lo descarta por completo por no encontrare la utilidad en el momento, al menos a mi parecer sería mucho mejor explicar estos conceptos con casos de uso real.

Closure y Lexical scope

Me la documentación de Mozilla Developer tratan al closure como un tipo de objeto.
Leer más

Les dejo esto que hice…

Input

const buildCount2 = (i) => {
  let count = i;
  const displayCount = () => {
    console.log(count);
    count += i;
  };
  return displayCount;
};

const myCount2 = buildCount2(2);

myCount2();
myCount2();
myCount2();
myCount2();
myCount2();
myCount2();

Output

2
4
6
8
10
12

Creo que la mejor forma de entender todo es experimentando un poco con el código. Aquí les dejo algo que hice. Consiste en contar en las cantidades que le indiquemos. Ej: si pongo 2 en buildCount(), la cuenta se va a hacer de 2 en 2.

Para los que tienen dudas sobre el valor de i.
Si ejecutas este código te mostrará el siguiente resultado.
1 1 2
2 2 3
3 3 4

const constructor = (i) =>{
    let count = i; 
    const displayOfCount = () =>{
        console.log(count, count++, count);
    }
    return displayOfCount;
};

const myCount = constructor(1);
myCount();
myCount();
myCount();

¿Por qué?
La variable constructor contiene una función anónima (arrow function) la cuál recibe un parametro i.
Dentro de la función: count es igual a i.
myCount es resultado de la variable constructor con el argumento 1.
En la primera ejecución count = 1;
Al realizar el console.log se imprime count (que tiene valor de 1), además imprime count++ que sigue con el mismo valor 1 (pero es incrementado por ++). Al final imprime count otra vez, solo que ahora tiene un valor de 2 debido al incremento.

una vez más Maestro Sacha al rescate explicando ambito lexico (y closures) de manera clara y profunda
https://www.youtube.com/watch?v=JXG_gQ0OF74

Se definre ámbito léxico ...

Ámbito léxico en closures

El ámbito léxico son las funciones que se ejecutan utilizando la cadena del alcance dónde estaba en su momento

const buildCount = (i) => {
  let count = i
  const displayCount = () => {
    console.log(count++)
  }
  return displayCount
}

const myCount = buildCount(1)
myCount()
myCount()
myCount()

const myOtherCount = buildCount(10)
myOtherCount()
myOtherCount()

El ámbito léxico es la forma en que podemos permitir acceder a variables por el lugar donde son declaradas, en este ejemplo, la variabel count fue declarada dentro de las llaves de la función buildCount pero la función displayCount puede acceder a la variable count debido a que están siendo declaradas en el mismo ámbito ó scope.

const buildCount = (i) => {
    let count = i;
    const displayCount = () => {
        console.log(count++)
    };
    return displayCount;
};

const myCount = buildCount(120);

myCount();
myCount();
myCount();

/* al inicializar la variable myCount con el valor del la funcion buildCount(120) lo que hacemos es iniciar la variable i con el valor de 20 y partir nuestro conteo desde ahi */

const myOtherCount = buildCount(10);

myOtherCount();
myOtherCount();

/* como esta es una nueva variable myOtherCount y en ella se establece un nuevo valor buildCount(10) nuestro conteo se reinicia y parte a partir del numero 10 */

otra vez la misma inexactitud no esta recordando nada lo que hace es asignar el valor a count…

Para que el script “recuerde” algo debe asignarlo a variable…

NO esta recordando esta asignando a la variable COUNT…

Tanto por procesar en este mundo de JS, por ello es importante complementar conocimientos entre documentaciones oficiales, videos y ejemplos

¡Genial está esto de los clousures! 👦🏻

vaya vaya ++ count, count ++ son diferentes, hoy aprendi algo nuevo

yo creo que una vez y le entiendo!!!

si aun tiene problemas con este termino, les recomiendo leer este articulo aqui!

Este link me ayudo bastante:
Entendiendo closure

Un poco más claro.