Hola, si llegaste aqui es porque en la clase ¿Qué es closure? te quedaron muchas dudas sobre lo que pasa por debajo.
Espero que este aporte ayude a entender lo que pasa , vamos a ver que es lo que pasa con el ejercicio moneyBox()
gráficamente con ayuda de JavaScript Visualizarer.
Javascript Visualizer es una herramienta de visualización de contexto de ejecución, hoisting, closures y scopes en JavaScript.
<h3>Instrucciones</h3>El vizualizador aún esta en fase Beta, lo que significa que por ahora solo soporta ES5, asi que tendermos que hacer ciertos cambios es el código de la clase.
const moneyBox = () => {
let saveCoins = 0
const countCoins = (coins) => {
saveCoins += coins
console.log(`MoneyBox: $${saveCoins}`)
}
return countCoins
}
let myMoneyBox = moneyBox()
myMoneyBox(4)// 4myMoneyBox(6)// 10myMoneyBox(10)// 20
Con estos cambios el visualizador ejecutara nuestro código sin problemas.
var moneyBox = function() {
var saveCoins = 0;
var countCoins = function(coins) {
saveCoins += coins;
console.log(saveCoins);
};
return countCoins;
};
var myMoneyBox = moneyBox();
myMoneyBox(4); //4
myMoneyBox(6); //10
myMoneyBox(10); //20
<h1>Ejecución</h1>
En la primera ejecución y en cada llamada a una nueva función se crea un contexto de ejecución la cual tiene dos fases:
undefined
.Como se puede obserbar el valor de moneyBox
paso de undefined
a fn()
ya que su contenido es una función.
El siguiente línea tiene algo más de complejidad.
var myMoneyBox = moneyBox();
//moneyBox() se ejecuta //y lo que retorna se guarda en myMoneyBox
Cuando llegamos a esta línea debemos ejecutar primero moneyBox()
el cual ya tiene definido una función fn()
que apunta a la línea 1.
Cada vez que se invoca una función se crea un nuevo contexto de ejecución, tambien crea un objeto
this
pero a diferencia del contexto global, crea un objeto llamadoarguments
.
Tambien tiene las dos fases de creación y ejecución
El objeto arguments
simplemente recibe los argumentos pasados cuando invocamos la funcion, es este caso queda vacío.
Las variables saveCoins
y countCoins
se declaran con el valor por defecto de undefined
.
Este es el bloque de código que se ejecutará.
var moneyBox = function() {
var saveCoins = 0;
var countCoins = function(coins) {
saveCoins += coins;
console.log(saveCoins);
};
return countCoins;
};
Las variable saveCoins
obtiene su valor 0
y countCoins
hará referencia a una función fn()
.
La función retornara countCoins: fn()
.
Cuando moneyBox()
termine de ejecutarse, JavaScript Visualizer creara un closure scope
.
Dentro de Closure Scope
existe el mismo entorno de ejecución que en moneyBox
es este caso => anonymous Execution Context.
Esto pasa debido a que tenemos una función anidada dentro de otra.
myMoneyBox
que esta en el contexto global recibe una función fn()
que hace referencia al Closure Scope
.Dado que myMoneyBox
ahora es una función hace refencia a función que se almacena en countCoins
que recibe un parametro coins
var moneyBox = function() {
var saveCoins = 0;
//==============================var countCoins = function(coins) {
saveCoins += coins;
console.log(saveCoins);
};
//==============================return countCoins;
};
<h4>Últimas lineas de código</h4>
myMoneyBox(4); //4
myMoneyBox(6); //10
myMoneyBox(10); //20
Esto es lo que sucede cuando ejecutamos myMoneyBox(4)
.
Closure scope
en la fase de creación.arguments
recibe un parámetro que esta vez es 4
.coins
esta se define como variable local dentro de esta función.saveCoins += coins
suma 0 + 4
y lo almacena en saveCoins
del closure scope.4
que al no existir en la anonymous Execution Context la busca en el scope padre más cercano que es Closure ScopeEl Closure Scope queda así con el valor de saveCoins
modificado
Notaran que con cada llamada a la función guardara el dato es su contexto de ejecución.
Cuando ejecutamos myMoneyBox(6)
primero en fase de creación y luego en ejecución.
Creación
Ejecucuión
Cuando ejecutamos myMoneyBox(10)
primero en fase de creación y luego en ejecución.
Creación
Ejecucuión
Si algunas cosas no te quedaron claras les recomiento el siguiente artículo.
Tambien pudes probar el código tu mismo en el siguiente enlace.
Qué es un closure