No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Practicando Closures

8/11
Recursos

Ahora que ya entiendes qué es un closure, te mostraré un ejemplo para emplearlo en un proyecto.

Cómo utilizar Closure para construir una alcancía

Si creamos una alcancía de la siguiente manera, solamente mostrará el valor enviado, no guardará la información del dinero que le enviamos.

function alcancia(monedas){
    let contenido = 0
    contenido = contenido + monedas
    return contenido
}

const miAlcancia = alcancia
miAlcancia(5) // 5
miAlcancia(4) // 4

Si utilizamos un closure, entonces la variable en que estará en un scope más elevado que la función interior, recordará el ámbito léxico que fue creada. Por lo tanto, cada vez que invoquemos cada función, mostrará el dinero ahorrado en la alcancía.

function alcancia(cantidadInicial){
  let contenido = cantidadInicial
  return function guardar(monedas){
    contenido = contenido + monedas
    return contenido
  }
}

const miAlcancia = alcancia(2)
miAlcancia(5) // 7
miAlcancia(4) // 11

const otraAlcancia = alcancia(5)
otraAlcancia(30) // 35
otraAlcancia(20) // 55

Contribución creada por Andrés Guano.

Aportes 41

Preguntas 8

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

Este es mi ejemplo. 😃

const maestro = "Dios";

function crearFamilia() {
  const abuela = "carlina";

  function hijosAbuela() {
    const hijoOne = "Martha";
    const hijoTwo = "Evelio";
    const hijoThree = "Rocio";

    function hijosDeHijosAbuela() {
      const hijosRocio = [{ nombre: "juan" }, { nombre: "andrea" }];
      const hijosMatha = [{ nombre: "Fabian" }, { nombre: "Heidy" }];
      const hijosEvelio = [
        { nombre: "Nathy" },
        { nombre: "Juancho" },
        { nombre: "Santiago" },
      ];
      return {
        generacion: function () {
          console.log(`
${maestro} crea a mi abuela ${abuela}
la abuela tuvo 3 hijos ${hijoOne} ${hijoTwo} ${hijoThree}
los hijos de la abuela tienen hijos. Rocio: ${hijosRocio[0].nombre} y  ${hijosRocio[1].nombre}
Martha: ${hijosMatha[0].nombre} y  ${hijosMatha[1].nombre}
Evelio: ${hijosEvelio[0].nombre} ${hijosEvelio[1].nombre} y ${hijosEvelio[2].nombre}
		`);
        },
      };
    }
    return hijosDeHijosAbuela();
  }
  return hijosAbuela();
}

const generar = crearFamilia();
console.log(generar.generacion()); 

¡Adiós al var!
.
Con esta técnica de Closures ya nos podemos evitar totalmente el uso de la palabra reservada var, ya no necesitamos una variable que sea global para almacenar un valor que vamos a usar/modificar dentro de alguna función o bloque, ahora podemos manejar y controlar una variable que solo existe dentro de la función que la va a modificar, limitando su alcance podemos evadir errores lógicos ya que si en otra función tenemos una variable con el mismo nombre, no afectará nuestra lógica y no nos dará resultados inesperados, porque literalmente será otra variable, independiente de la que creamos en nuestra primera función. 😌
.
¿Y qué pasa si yo creo una variable dentro de una función y también la quiero usar en otra función? 😰
Tranqui… existe la palabra reservada return que nos ayudará a extraer el valor de nuestra variable y colocarla en otro contexto o alcance.
.
Con cada clase, Oscar nos va mostrando la manera correcta de programar para no caer en malas prácticas. 👨🏽‍🏫

Les dejo este algoritmo que hace un bonito mosaico.

function mosaico() {
  const figuras = [];

  function pintar(nuevaFigura) {
    figuras.push(nuevaFigura);

    let resultado = '';
    const mainLength = figuras.length * 2;
    
    for (let fila = 0; fila < mainLength; fila++) {

      for(let columna = 0; columna < mainLength; columna++) {
        const valorMax = fila > columna ? fila : columna;
        const valorMin = fila < columna ? fila : columna;

        const valorPosible = mainLength - (valorMax + 1);

        const indexFigura = valorPosible < valorMin ? valorPosible : valorMin;
        

        resultado += `${figuras[indexFigura]} `;
      }
      resultado += '\n';
    }
    return resultado;
  }

  return pintar;

}

const m = mosaico();
console.log(m('*'));
console.log(m('o'));
console.log(m('+'));
console.log(m('x'));
Woou, tenía tiempo usando JavaScript de lo que había aprendido de forma autónoma, pero desde que entre a Platzi nunca paro de aprender nuevos conceptos y/o funcionalidades cómo las Closures

Mi ejemplo!

function family() {
  let family = [];
  function addMember(member) {
    family.push(member)
    console.log(`Esta familia está compuesta por ${family}`)
  }
  return addMember;
}

let petersFamily = family();
petersFamily('Peter');
petersFamily('Camille');
petersFamily('John');
let emilysFamily = family();
emilysFamily('Emily')
emilysFamily('Carl')
emilysFamily('Sophy')

A mí se me ocurrió este ejemplo:

.

La función moneyBox devuelve un objeto con funciones que «recuerdan» ownerName y totalMoney.

.

Además, agrego una manera en la que se pueden renombrar cada una de las funciones devueltas en el objeto retornado.

.

Espero que les sirva. 💚

Esto hace lo mismo pero con el return como una funcion llamada directamente

const moneyBox = () => {
    let saveCoins = 0;
    
    return (coins) => {
        saveCoins += coins;
        console.log(`MoneyBox: $${saveCoins}`);
    }
}

const myMoneyBox = moneyBox();
myMoneyBox(5);
myMoneyBox(5);
myMoneyBox(20);
console.log('-----------------')
const myMoneyBoxHector = moneyBox();
myMoneyBoxHector(10);
myMoneyBoxHector(10);```

Quiero decir primero que todo que me ayude mucho mirando este video me ayudo a entender mas de como funcionan y como podemos implementarlos

CODE:

function moneyBox (){
    
    let saveCoins = 0 ;

    return {
        depositar: function countCoins (coins){
            saveCoins+=coins;
        },
        retirar: function countCoins (coins){
            saveCoins-=coins;
        },
        saldo: function countCoins (){
            return saveCoins
        }

    }

}

const moneyBoxAna = moneyBox();
console.log(moneyBoxAna.saldo());
moneyBoxAna.depositar(5);
console.log(moneyBoxAna.saldo());
moneyBoxAna.retirar(1)
console.log(moneyBoxAna.saldo());

RESULTADO:

Fuf! excelente, muy bien, el ejemplo de la alcancía me queda claro. Cuando usamos la función sin aplicar clousures, la variable savemoney siempre se inicializa en 0 y al ingresar un valor termina ejecutandose el 0 = 0+coins, por eso siempre da el valor que se ingresa. Pero al aplicar clousures es como si a esta variable que se encuentra en un ambito léxico superior le reasignaramos el valor. Es interesante

Programación funcional

En este paradigma existe algo que se llama composición de funciones, closures y Currying.

Composición de funciones o funciones compuestas

Son el resultado de combinar 2 o más funciones, el resultado de cada función es el argumento de la siguiente y así sucesivamente

addOne(timesTwo(1))

Closure

Fue explicado la clase anterior

Currying

Gracias a los closures es posible implementar el Currying. Esto es descomponer funciones complejas en otras funciones más pequeñas donde cada función recibe un solo argumento.

// Sin Currying
function sumThreeNumbers(a, b, c) {
  return a + b + c
}

console.log(sumThreeNumbers(1, 2, 3)) // 6

// Con Currying
function sumThreeNumbers(a) {
  return function(b) {
    return function(c) {
      return a + b + c
    }
  }
}

console.log(sumThreeNumbers(1)(2)(3)) // 6

Código ejemplo clase 8

function moneyBox(){
let saveCoins =0;
functions countCoins(coins){

saveCoins +=coins;
console.log( `MoneyBox: $${saveCoins}`)

}
return countCoins;
}

const myMoneyBox = moneyBox();
myMoneyBox(5); //ahorra 5
myMoneyBox(5); //ahorra 10
myMoneyBox(15) //ahorra 25

Aquí un ejemplo de lo que se puede hacer, lo tome de un proyecto que hice durante el curso de js basico, en un principio lo tenia todo como funciones sueltas en el scope global pero durante este curso me di cuenta que podía utilizar un función con clouser para simplificarlo y hacer el código un poco más elegante
Alguien con más conocimientos sobre el tema me puede decir si hice bien?? siento que hay algo mal pero no estoy seguro

Me esta costando entender mucho este concepto, pero basandome en el ejercicio de myMoneyBox, pude crear este codigo que seria ir agregando articulos a un Carrito de compras, para una tienda en especifico.

function shoppingCart(){
    let cart = [];
    function addItems(item){
        cart.push(item);
        console.log(cart);
    }
    return addItems;
}

const amazon = shoppingCart();
amazon("Mouse");
amazon("Keyboard");
amazon(`Display 24"`);

Que opinan?

También podemos retornar funciones que le creamos internamente. Sí ven este código y vienen de React se darán cuenta que es lo mismo que hacemos con los hooks.

function moneyBox(initialAmount = 0) {
    let amount = initialAmount;

    function add(quantity) {
        amount += quantity;
        console.log(`Amount = ${amount}`);
        return amount;
    }

    function subtract(quantity) {
        amount -= quantity;
        console.log(`Amount = ${amount}`);
        return amount;
    }

    function getAmount() {
        console.log(`Amount = ${amount}`);
        return amount;
    }

    return {
        add,
        subtract,
        getAmount,
    }
}


const {add, subtract, getAmount} = moneyBox(10);

getAmount(); // Amount = 0
add(10); // Amount = 20
add(5); // Amount = 25
subtract(2) // Amount = 23
subtract(1) // Amount = 22
getAmount(); // Amount = 22

Hice una funcion para manejar presupuesto mensual.

function presupuestoMensual() {
    let salario = 2000000;
    function gastos(compras){
        salario -= compras;
        console.log(`expend: $${salario}`);
    }
    return gastos;
}
const misGastos = presupuestoMensual();
misGastos(300000);
misGastos(40000);

Yo hice un programa que me permite saber si las calorías consumidas de una dieta hipercalórica estaba siendo seguida a regla o no.

function caloriasConsumidas (){
    let sumaDeGramos = 0;
    function totalIngesta(gramos){
        sumaDeGramos += gramos;
        if(sumaDeGramos > 2200 && sumaDeGramos < 2650 ){
            console.log(`Excelente trabajo lograste ${sumaDeGramos} kcal hoy, sigue asi!`);
        } else if(sumaDeGramos < 2199){ 
           console.log (`Aun no se logra el objetivo calorico de hoy ¡Sigue comiendo!`)
        } else {
            console.log(`Creo que debes reducir tu ingesta`)
        }
    }
        return totalIngesta
    }
 
    
    

const ingestaDeJuanm = caloriasConsumidas() 

ingestaDeJuanm(450);
ingestaDeJuanm(520);
ingestaDeJuanm(600);
ingestaDeJuanm(450);
ingestaDeJuanm(350);
            function pokemondanio(vida){
                let puntosVida = vida;

                function restaDanioPoke(danio){
                    puntosVida = puntosVida - danio;
                    console.log("a bajado a " + puntosVida);
                }
                return restaDanioPoke;
            }

            gengar = pokemondanio(1200); //damos el valor de la vida
            gengar(200); //damos la cantidad que baja

            pikachu = pokemondanio(600); 
            pikachu(100);
// Utilizar closures para saber la cuenta del super que hizo cada persona.

function purchaseGroceries () {
    let groceries = [];
    let x = 0
    function purchase (item) {
        groceries.push(item);
        console.log(groceries);

    }
    return purchase;
}

const checkChristian =purchaseGroceries();
checkChristian('meat');
checkChristian('apples');
checkChristian(['onions', 'garlic']);

My exercise

function createList(){
    let listItem = [];

    function addItems(item){
        listItem.push(item);
        console.log(listItem);
    }
    return addItems;
}

let firstList = createList();

firstList("Shoes");
firstList("Shirt");
firstList("Dress");

let secondList = createList();

secondList("Phone");
secondList("Headphone");
secondList("TV");

Mi ejemplo

// Ejemplo
function ventasAutos() {
    let count = 0;
    let autos = [];
    function auto(color, marca){
        count += 1;
        autos.push([color, marca]);
        console.log(autos);
        console.log(count);
    }
    return auto;
}

const ventasJuan = ventasAutos();
ventasJuan("azul", "ford");
ventasJuan("rojo", "ford");

const ventasAna = ventasAutos();
ventasAna("gris", "fiat");
ventasAna("blanco", "fiat");
ventasAna("negro", "fiat");

Cre que por el primer contexto sin closure no suma las monedas, en mi opinion.

Adjunto mi aporte. Tomé la idea del carrito de compras del comentario de Ricardo Mejía y me puse a experimentar un poco con los métodos de arreglos del curso de manipulación de arrays hasta obtener el siguiente resultado:

function productos() {
    let agregarCarrito = [];
    
    function agregarProducto(producto) {
        let valorProducto = Number((Math.random()*10).toFixed(2));
        agregarCarrito.push({
            producto: producto,
            valor: valorProducto,
        });
    }

    function eliminarProducto(producto){
        const productoEliminado = agregarCarrito.find((value) => value.producto == producto);
        console.log(`Eliminaste '${productoEliminado.producto}' del carrito`);
        agregarCarrito.splice(agregarCarrito.findIndex(index => index.producto === producto), 1);
        total();
    }

    function mostrarProductos(){
        console.log(agregarCarrito.map((value) => `${value.producto}: $${value.valor}`));
    }

    function total(){
        let totalProductos = (agregarCarrito.reduce((sum, values) => sum + values.valor, 0)).toFixed(2);
        console.log(`El total del carrito es: $${totalProductos}`);
	console.log('');
    }

    return {
        agregarProducto,
        eliminarProducto,
        mostrarProductos,
        total,
    };
}

const carrito = productos();

carrito.agregarProducto('Galletas');
carrito.agregarProducto('Chocolate');
carrito.agregarProducto('Avena');
carrito.agregarProducto('Leche');
carrito.agregarProducto('Azúcar');
carrito.mostrarProductos();
carrito.total();

carrito.eliminarProducto('Chocolate');
carrito.eliminarProducto('Leche');
carrito.mostrarProductos();

carrito.agregarProducto('Arroz');
carrito.mostrarProductos();
carrito.total();

/*imprime:
[
  'Galletas: $4.67',
  'Chocolate: $1.34',
  'Avena: $4.22',
  'Leche: $2.76',
  'Azúcar: $2.72'
]
El total del carrito es: $15.71

Eliminaste 'Chocolate' del carrito
El total del carrito es: $14.37

Eliminaste 'Leche' del carrito
El total del carrito es: $11.61

[ 'Galletas: $4.67', 'Avena: $4.22', 'Azúcar: $2.72' ]
[ 'Galletas: $4.67', 'Avena: $4.22', 'Azúcar: $2.72', 'Arroz: $7.88' ]
El total del carrito es: $19.49*/

en teoria deberia de funcionar 😁

Ejemplo:

// dinero gastado en Castillo Furioso, historial de compras de Play Store. Tengo $1000 de credito, hice 3 compras, quieor ver cuanto me queda.

function ComprasDeGoogle() {
    let saveCoins = 1000;
    function countCoins(coins) {
        saveCoins -= coins;
        console.log(`ComprasDeGoogle: $${saveCoins}`)
    }
    return countCoins;
}

const GemasCC = ComprasDeGoogle();
GemasCC(249.99);
GemasCC(149.99);
GemasCC(49.99);

Resultado:

[Running] node "c:\Users\..**..js**

ComprasDeGoogle: $750.01
ComprasDeGoogle: $600.02
ComprasDeGoogle: $550.03

[Done] exited with code=0 in 0.101 seconds

Para comentar en cualquier lenguaje es:

ctrl + k
y luego,
ctrl + c

Solo veo que imprime

Les comparto un fragmento de mi código en donde tuve que usar closures para mi página web personal. El código está en TypeScript. 😄
Link del repositorio

import { buttonMoreAboutMe, textMoreAboutMe } from "./components/htmlElements.js";

const originalDates = (): () => number => {
    let inicialNumber = 0;
    return function (): number {
        inicialNumber++;
        return inicialNumber;
    };
};

const showMoreAboutMe = (): void => {
    textMoreAboutMe.classList.toggle('visibleMoreAboutme');
    if (condition() % 2 === 0) {
        buttonMoreAboutMe.innerText = 'Leer más';
    } else {
        buttonMoreAboutMe.innerText = 'Leer menos';
    }
};

const condition = originalDates();
buttonMoreAboutMe.onclick = () => showMoreAboutMe();

Este es mi pequeño ejemplo:

function moneyBox() {
    let _quantityCoins = 0;
    function saveCoins(coins) {
        return _quantityCoins += coins;
    }
    function takeCoins(coins) {
        return _quantityCoins -= coins;
    }
    function showCoins() {
        console.log(`MoneyBox: $${_quantityCoins}`);
    }
    return {
        saveCoins,
        takeCoins,
        showCoins
    }
};

const moneyBoxAna = moneyBox();
moneyBoxAna.saveCoins(10);
moneyBoxAna.saveCoins(1);
moneyBoxAna.takeCoins(3);
moneyBoxAna.showCoins();

Mi código con una pequeñita modificación para saber de quien es el box de ahorro.

function moneyBox() {
    let saveCoins = 0;

    function countCoins(coins, name) {
        saveCoins += coins;
        console.log(`Que tal, ${name}, llevas ahorrado: $${saveCoins}`);
    }
    return countCoins;
}

const myBox = moneyBox();
myBox(10, 'Rafael');
myBox(20, 'Rafael');
myBox(15, 'Rafael');

closure funciona muy parecido a otros lenguajes que he usado.

He aqui mi ejemplo, he retornado directamente la funcion y tambien agregado la variable “owner” para identificar a quien pertenece la alcancia:

function moneyBox(owner) {
  let savedCoins = 0;
  return (coins) => {
    savedCoins += coins;
    console.log(`${owner}'s' MoneyBox: $${savedCoins}`);
  };
}

const juanMoneyBox = moneyBox("Juan");
myMoneyBox(5);
myMoneyBox(3);
myMoneyBox(15);

const anaMoneyBox = moneyBox("Ana");
pepitaMoneyBox(100);
pepitaMoneyBox(100);
pepitaMoneyBox(100);

Este es mi ejemplo 😃

function closureExample() {
    let _number = 0;

    function increase(num) {
        return _number += num;
    }

    function decrease(num) {
        if(num >= _number){
            return _number = 0;
        } else {
            return _number -= num;
        }
    }
    function getNumber(){
        return _number;
    }

    function setNumber(num){
        return _number = num;
    }

    return {
        increase,
        decrease,
        getNumber,
        setNumber,
    }
}

const calc = closureExample();

calc.setNumber(12)
calc.increase(4);
calc.decrease(6);
//console.log(calc.setNumber(25));
console.log(calc.getNumber());

const calc1 = closureExample();
calc1.setNumber(30);
console.log(`la calculadora 2 tiene como numero: ${calc1.getNumber()}`)

function headShot() {
let shots = 0;
function shotCounts(bullets) {
shots += bullets;
console.log(You have succeeded: $${shots} headshots ▄︻̷̿┻̿═━一);
}
return shotCounts;
}

const Shots = headShot();
Shots(2);
Shots(4);
Shots(2);

😉Hola, la función retornará “… $5” en los dos casos porque
Suma el valor del argumento Coins con la variable saveCoins que al ejecutar la función siempre se declara con el valor de 0.

function moneyBox(coins) {
    let saveCoins = 0; 
    // Siempre se declara de nuevo, al ejecutar la funcion con el valor de 0.
    saveCoins += coins;
    console.log(`MoneyBox $${saveCoins}`);
    /* > MoneyBox $(0 + coins)*/
}

moneyBox(5);
/* > MoneyBox $5*/
moneyBox(5);
/* > MoneyBox $5*/

🎉🎉 ¡Fábrica LaMadre abre sus puertas! 🎉🎉

Aquí tienes un ejemplo para crear tu propia familia:

function fabricaLaMadre(madre, padre){
    let nombreH = [];
    let nombreM = [];

    function familia(n1,n2){
        nombreH.push(n1);
        nombreM.push(n2);
        console.log(`${madre} y ${padre} son los padres de ${nombreH} y de ${nombreM}`)
    }

    return familia

}

Con sólo una declaración puedes crear una pequeña famlia, así:

const Maria = fabricaLaMadre("Maria","Carlos");

Has creado la Familia María con María siendo la Madre y Carlos supuestamente es el padre.

Cuando invoques la función dentro de María, no olvides agregar el nombre del hijo y de la hija:

Maria("Juano","Juana")

Y en menos de lo que tardas en lamentar no haber usado sombrerito ya tendrás na hermosa familia feliz:

// Output:

"Maria y Carlos son los padres de Juano y de Juana"

Ejecútalo : https://codepen.io/diego-granados-the-styleful/pen/vYREayP

//Ejemplo de closure

function carrito () {
    let elementsCarrito = [];
    let count = 0;
    function AddElementsCarrito (Element) {
        elementsCarrito.push(Element);
        count +=1;
        console.log(`El carrito tiene: ${elementsCarrito} y van ${count} artículos`);
    }
    return AddElementsCarrito;
}
const mycarrito =carrito();
mycarrito('gaming keyboard');
mycarrito('30 pulgMonitor'); 
mycarrito('headphones');
mycarrito('Smart Watch'); 

Code:

function moneyBox() {
    let saveCoins = 0;

    function countCoins(coins){
        saveCoins += coins;
        console.log(`Money Box: $${saveCoins}`);
    }
    return countCoins;
}
const myMoneyBox = moneyBox();
myMoneyBox(5);
myMoneyBox(10);
myMoneyBox(15);

Muy ilustrativo. Siempre me pregunté como hacer para recordar valores acumulados. Ahora ya se como 😄

Excelente me quedo mas claro con este ejemplo

En el principio tomaría el valor que le pasamos, ya que cada que ejecutamos moneyBox reasignamos el valor de saveCoins.