No tienes acceso a esta clase

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

Map Reloaded

6/28
Recursos

Ahora que ya sabes cómo funciona el método map de arrays estudiemos diferentes situaciones que deberás manejar array de objetos como los siguientes datos de orders.

const orders = [
  {
    customerName: "Nicolas",
    total: 60,
    delivered: true,
  },
  {
    customerName: "Zulema",
    total: 120,
    delivered: false,
  },
  {
    customerName: "Santiago",
    total: 180,
    delivered: true,
  },
  {
    customerName: "Valentina",
    total: 240,
    delivered: true,
  },
]

Extrayendo datos necesarios

De un conjunto de datos a veces necesitas ciertos atributos para realizar una operación, extraer los nombres o cuantificar un suceso. El método map te permite extraer estos datos según los puedas utilizar.

const totales = orders.map(order => order.total)

console.log(totales) // [ 60, 120, 180, 240 ]

Transformando objetos dentro de un array

De un conjunto de datos, de los cuales son objetos, a veces requieres añadir una propiedad nueva o eliminar una que no es necesaria. Si necesitas transformar objetos dentro de un array, debes tener en cuenta que cada objeto tiene una referencia en memoria propia. Por lo que si transformas un objeto, también lo harás en el original como en el nuevo, aun cuando el método map es inmutable.

Los parámetros por referencia los debes tener presente cuando manejes objetos y arrays.

// Ejemplo donde transformas los objetos originales
const tarifas = orders.map(order => {
    order.tax = 0.19
    return order
})

tarifas[0] === orders[0] // true
tarifas[1] === orders[1] // true

Una forma de evitar este comportamiento, es crear un nuevo objeto con el spread operator (operador de propagación).

// Ejemplo donde no transformas los objetos originales
const tarifas = orders.map(order => {
    return {
        ...order,
        item: 0.19,
    }
})

tarifas[0] === orders[0] // false
tarifas[1] === orders[1] // false

Contribución creada por: Andrés Guano.

Aportes 62

Preguntas 7

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Esta clase es otro nivel. Yo hubiera pensado que map mutó mi array, pero resulta que no, que solo lo dejó en la referencia de la memoria. Y la técnica para agregar sin cambiar la referencia vale su peso en oro. Por cosas así es que pago por Platzi.

Aquí va el array de objetos para el ejercicio 😃

const orders = [
  {
    customerName: "Nicolas",
    total: 60,
    delivered: true,
  },
  {
    customerName: "Zulema",
    total: 120,
    delivered: false,
  },
  {
    customerName: "Santiago",
    total: 180,
    delivered: true,
  },
  {
    customerName: "Valentina",
    total: 240,
    delivered: true,
  },
];

Usos comunes o clásicos de map() sobre los arrays:

  • Limpiar datos, seleccionar datos dentro de un array y devolverlos para su utilización en futuras acciones.
  • Añadir un nuevo elemento, modificar agregando un nuevo dato al objeto pero sin modificar el array original.

.
Tener en cuenta que cuando trabajamos con objetos y map() y retornamos el mismo objeto estamos copiando la referencia en memoria que tiene el objeto original que le aplicamos el map() (esto lo vimos en la clase de mutable vs inmutable, te dejo una lectura: https://platzi.com/tutoriales/1642-javascript-profesional/4559-estructuras-de-datos-inmutables/). Esto provoca que como estamos modificando la referencia en memoria, el array original también sea modificado. Entonces en conclusión, por más que map() sea inmutable en este punto estamos copiando la referencia en memoria y por eso hace el cambio en el original.

// Estamos retornando el objeto
// por ende se copia la refencia en memoria
const rta = orders.map(item => {
    item.tax = .19
    return item;
})

Para evitarlo, y poder realizar una copia y evitar la referencia en memoria, utilizamos el spread operator de ES6 (https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Operators/Spread_syntax), donde generamos un nuevo objeto con los valores del objeto original y luego agregamos el nuevo valor que nos interesa.

const rta = orders.map(item => {
    // retornamos un nuevo objeto 
    //pero evitamos hacer ref. en memoria
    return {
        ...item,
        tax: .19,
    }
})

Y esas líneas se pueden reducir aún más 😃:

const withTax = orders.map(order => ({ ...order, tax: .17 }))

Para entender por qué se modifica el array cuando trabajamos con objetos les recomiendo la clase donde JuanDC nos explica como funciona la memoria en JS:
https://platzi.com/clases/2419-javascript-poo-intermedio/39811-como-funciona-la-memoria-en-javascript/

Faltó como modificar una propiedad en otra referencia en memoria sin modificar el original:

// Modificar el original en otro objeto en memoria
const resp4 = orders.map(item => {
    return {
        ...item,
        total: item.total + 5,
    };
});
console.log('Resp4:', resp4);
console.log('Original:', orders);

Spread Operator

Utilizando el spread operator, cogemos los valores de person y los insertamos directamente en X. Así evitamos anidar un abjeto dentro de otro
Con el spread operator, podemos sumar arrays, hacer copias, añadir nuevos elementos…

Fuente: https://dev.to/lydiahallie/interactive-javascript-quiz-2-4pi1

Tener cuidado con el spread operator. si el objeto contiene otros objetos, se seguirán copiando las referencias en memoria de estos. Les recomiendo el curso POO intermedio donde profundiza este tema.

Los navegadores web usan dos tipos de memorias: Stack y Heap.

Stack

Es veloz, pero sin tanto espacio.

Aquí se guardan los valores primitivos (booleanos, strings, números…).

Heap

Es más lenta, pero permite guardar enormes cantidades de información.

De mis métodos favoritos ❤️ el array map, realmente te ayuda a hacer un código mucho más limpio y a implementar o mapear todo para evitar errores al momento de trabajar con arrays de objetos que no traigan la información en un formato correspondiente, por ejemplo, si el objeto trae los números en cadenas de caracteres puedes transformarlos en números dentro del map y evitarte validaciones futuras.

cuando trabajamos con objetos hay que entender un concepto muy importante a la hora de copiarlos
La referencia en memoria:
Cuando creamos un objeto, este es almacenado en dos tipos de memorias:
memoria stack:
-Esta es una memoria dinámica pero con poco espacio

  • En esta memoria es donde se almacenan las inicializaciones de las variables, objetos, array, Junto con las declaraciones de los valores primitivos.

memoria heap:
-Esta es una memoria mas lenta pero mas ordenada y con mas espacio
-En esta memoria es donde se almacenan los arrays y los objetos

  • Cuando se inicializa y se declara un array o un objeto, los que se hace es almacenar el array/objeto en la memoria heap,
    y la declaración de la misma se almacena en la memoria stack
    Por lo tanto la declaración es un pointer desde la memoria stack hacia el objeto que esta en la memoria heap

Que joyita de clase 😮😮

Podriamos agregar la propiedad tax de una manera un poco mas real de la siguiente manera:

const products = [
  { name: "Chiken", price: 43 },
  { name: "Ken", price: 12 },
  { name: "Horse", price: 234 },
];

const wTax = products.map((product) => {
  let thetax = product.price * 0.16;
  return {
    ...product,
    tax: thetax,
    total: thetax + product.price
  };
});

console.log("original", products);
console.log("with tax", wTax);

Spread Operator

Esto puede ser muy útil en casos donde tenemos que pasar una lista de argumentos (no un array) a un método/función.

Antes de comenzar es importante resaltar el spread operator fue incluido en la nueva versión de Javascript ES6 y ya funciona en todos los navegadores.

Comencemos!

let numeros = [4, 16, 25, 2, 45, 8];

let numeroMayor = Math.max(numeros);

console.log(numeroMayor); // NaN

Observamos que el valor de la variable numeroMayor es NAN, esto es porque el método max() puede recibir una lista de argumentos y no le podemos pasar un array.

Entonces podríamos hacer los siguiente:

let numeroMayor = Math.max(4, 16, 25, 2, 45, 8);

console.log(numeroMayor); // 45

Ahora sí podemos acceder al número más alto de la lista de argumentos. De todos modos podemos mejorar este código gracias al spread operator.

Veamos cómo hacerlo!

let numeros = [4, 16, 25, 2, 45, 8];

let numeroMayor = Math.max(...numeros);

console.log(numeroMayor); // 45

Al anteponer los tres puntos que representan al spread operator transformamos la variable numeros (que en el ejemplo representa un array con números) en una lista de argumentos, y es por ello que podemos acceder al número mayor del array numeros. Es como si le quitáramos los corchetes ( “[]” ) al array.

let numeros = [10, 4, 7, 15, 3, 25];

console.log(numeros); // Imprime un array.

console.log(...numeros); // Imprime una lista de argumentos.

Os dejo 2 videos excelentes sobre el concepto de programacion funcional y el uso de estas funciones 😃

https://www.youtube.com/watch?v=3eLx9syx8iI&t=949s

Para agregar un nuevo atributo sin mutar, también se puede hacer de esta otra forma. Es exactamente lo mismo pero a mi parecer un poco mas limpio

const rta3 = orders.map(item => ({
  ...item,
  tax: 0.19
}))

Envolvemos los corchetes entre parentesis
item => ({

Utilizando

  return {
    ...item,
    tax: 0.19,
  };

Podemos crear una copia del objeto original y modificar esa copia, agregando ese nuevo elemento, sin modificar al array original de objetos.

Tener en cuenta todos los parametros que puede usar la funcion map que pueden ser utiles para algun caso:
1. currentItem
2. currentIndex
3. originalArray

const objA = [{quantity:20, price:1}, {quantity:2, price:4}];
const objE = objA.map( (currentItem, currentIndex, originalArray) => {
  return { …currentItem,
    index: currentIndex,
    total: currentItem.quantity * currentItem.price
  };
});

Otra forma de evitar copiar las referencias en memoria es asi…

const orders = [
  {
    customerName: "Nicolas",
    total: 60,
    delivered: true,
  },
  {
    customerName: "Zulema",
    total: 120,
    delivered: false,
  },
  {
    customerName: "Santiago",
    total: 180,
    delivered: true,
  },
  {
    customerName: "Valentina",
    total: 240,
    delivered: true,
  },
];

/* Aqui viene lo interesante */

let withTax = JSON.parse(JSON.stringify(orders))
withTax.map(e=>e.tax=.19)
console.warn(orders)
console.log(withTax)
  • Donde JSON.stringify() Convertira un Objeto
    en un string

  • yyyy JSON.parse() Toma un string y
    devuelve un objeto sin importar que tan complejo sea

Os dejo 2 clases al respecto

Es importante resaltar que este método para generar arrays con inmutabilidad solo funciona para la primera capa dentro del array

es decir si tenemos un array de objetos que además tiene objetos dentro de los objetos, y seguido de eso aplicamos el metodo para generar un nuevo array, la inmutabilidad solo se aplicara para la primera capa, en las siguientes capas se haran copias de las referencias en memoria de los objetos

vale la pena revisar estos links para entender un poco mejor como funciona

https://developer.mozilla.org/en-US/docs/Glossary/Shallow_copy

https://developer.mozilla.org/en-US/docs/Glossary/Deep_copy

en resumen, estaríamos haciendo un shallow copy

En resumen quien causa o evita la mutabilidad es la linea o bloque del return.

Me gustan mucho las clases de no mas de 10-12 minutos, son ideales para tomar notas e ir practicando lo aprendido, lo que no me pasa con clases de 25-30 minutos, donde siento que pierdo el hilo.

un dato interesante si necesitamos pasarle un atributo en especifico del objecto ejemplo total seria asi: ({propertyObject})
({total})

console.log('orginal', orders);
const resp = orders.map(({total}) => total);  
console.log('new', resp); //RESPUESTA SERIA new [ 60, 120, 180, 240 ]

que genial esta clase, el profe explica super bien, claro y preciso y aparte los ejemplos que brindan ayudan un montón, no sabia que esto sucedía ni el por que, que espectacular de verdad ❤️ .

Los primitivos se pasan por valor y los objetos se pasan por referencia, por ejemplo:

// Primitivos
let num = 10;
let num2 = num;
num2 = 2;
console.log( num );
console.log( num2 ); 

// Objetos
let car = { name: 'Mazda' };
let car2 = car;
let car2.name = 'BMW'
console.log( car );
console.log( car2 ); 

Para evitar el paso por referencia, tenemos métodos como Object.assign y el Spread Operator,

Ejemplo de la clase:

const rta2 = orders.map(order => ({...order, tax: 0.19}) );
const rta3 = orders.map(({...order}) => {
  order.tax = 0.19;
  return order;
});

Me imagino que la mutabilidad en los objetos sucede porque map solo trabaja en la memoria stack. Y como ahí solo guarda las referencias, no los valores, se afectan los valores en la heap.

Corríjanme si me equivoco.

map nos sirve para recorrer los elementos de un array y transformarlos.

Syntaxis


const numeros = [1,4,5,15]; 
const dobles = numeros.map(function(numero,position,numeros){
    return numero * 2;
}
  1. se invoca el método map sobre el array original.
  2. map recibe como primer parametro la función transformadora. La que se va a ir invocando por cada elemento del array
  3. esta función recibe como parámetro el elemento del array que va a transformar.
  4. segundo parámetro la posición del elemento en el array
  5. El tercer parametro es el array original donde se invocó la función

Muy importante el manejo de los objetos ya que se toma la referencia en memoria y si se muta el resultado.

Para hecer una copia del objeto y hacer la copia debemos generar un nuevo objeto usando el operador (…) de ECMAScript 6

Por si tienen problemas para mostrar en consola los arreglos: `console.log("Nuevo arreglo " json.stringify(rta3))`

También podíamos hacerlo con los poderosos métodos que nos dió el profe Juan David, JSON.stringify() para copiar los objetos como strings y luego JSON.parse() y regresarlos a objetos:

const ordersTax = orders.map( order => {
    const aux = JSON.stringify( order );
    const orderTax = JSON.parse( aux );
    orderTax.tax = 0.19;

    return orderTax;
} ) 

Estos cursos se complementan a la perfección

no se si estoy bien o mal , pero mas alla de que el array apunte a la referencia del objeto, principalmente se debe a que realiza un callback del elemento, o sea estoy llamando “AL OBJETO” y estoy modificando directamente “AL OBJETO”.

Tkm Spread Operator

Mira Marge soy un ¡desarrollador!

<var vehiculos = [

    {
        Marca: "Megane",
        Color : "Gris",
        carroseria : "Sedan",
        puertas: 2,
    },
    {
        Marca: "Chevrolet",
        Color : "Azul",
        carroseria : "Hachtback",
        puertas:4,
    }
];

const vehiculos2 = vehiculos.map(vehiculo =>{
   return {
       ...vehiculo,
       item: 0.19,
   }
});


console.table( vehiculos)
console.table( vehiculos2)> 

Lo gracioso es que cuando mencionó el ejercicio me puse a hacerlo antes de verlo y lo intenté como se hizo al final, luego vi que no fue así y lo cambié para que al final lo tuviera que volver a poner como lo hice al principio jaja, interesante.

Un pequeño resumen de esta clase:

Imagen generada con ray.so

Para hacer que el impuesto sea el 19% de cada pedido lo podemos hacer de la siguiente forma

const ordenes3 = ordenes.map((item) => {
    return {
        ...item,
        impuesto: .19 * item.total
    }
})

Cuando entiendes , todo se vuelve mas bonito, que gran clase!!! vamos bien con la primera parte…

Aqui mi codigo pero no se cambio nada como dice el profesor, cuando no estoy utilizando el spread operator

const orders = [
  {
    customerName: "Nicolas",
    total: 60,
    delivered: true,
  },
  {
    customerName: "Zulema",
    total: 120,
    delivered: false,
  },
  {
    customerName: "Santiago",
    total: 180,
    delivered: true,
  },
  {
    customerName: "Valentina",
    total: 240,
    delivered: true,
  },
];

console.log("orders", orders);
const soloTotal = orders.map((item) => item.total);
console.log("Solo los precios", soloTotal);

// MODIFICANDO UN ARRAY PARA ANADIR UN NUEVO ELEMENTO

const array2 = orders.map((item) => {
  item.tax = 0.19;
  return item;
});
console.log("array2", array2);

aqui esta el output

orders [
  { customerName: 'Nicolas', total: 60, delivered: true },
  { customerName: 'Zulema', total: 120, delivered: false },
  { customerName: 'Santiago', total: 180, delivered: true },
  { customerName: 'Valentina', total: 240, delivered: true }
]
Solo los precios [ 60, 120, 180, 240 ]
array2 [
  { customerName: 'Nicolas', total: 60, delivered: true, tax: 0.19 },
  { customerName: 'Zulema', total: 120, delivered: false, tax: 0.19 },
  { customerName: 'Santiago', total: 180, delivered: true, tax: 0.19 },
  { customerName: 'Valentina', total: 240, delivered: true, tax: 0.19 }
]

si se hubiese impreso el orginal mas arriba no ocurre la modificacion del original

Así quedó con un poco de estilos y aplicando eachFor en para mi nuevo array de objetos con Map.

 // Ejercicio de ordenes de compra 
 const bill = document.getElementById('bill');
 
 const orders=[
    {
        customerName:"Nicolas",
        total:60,
        delivered:true,
    },
    {
        customerName:"Zulema",
        total:120,
        delivered:false,
    },
    {
        customerName:"Santiago",
        total:180,
        delivered:true,
    },
    {
        customerName:"Valentina",
        total:240,
        delivered:true,
    },
];

const taxes = orders.map (item => {
    return {
        ...item,
        tax : item.total * 0.19
    }
});

const finalTotal = taxes.map (item =>{
    return {
        ...item,
        pagar : item.total + item.tax
    }
})


finalTotal.forEach(order => {
    bill.innerHTML += `<li class = 'bill--individual'> 
    <p class='titulo'> Recibo de compra para ${order.customerName}, ojalá disfrutes tu árticulo. </p>
    <input type= 'checkbox' ${order.delivered ? 'checked' : ''}/> <span> Tu orden fué entregada con éxito.</span>
                            <p> El costo de tu compra es de: <span class='numeros'>$${order.total}</span> </p>
                            <p class='impuestos'> Impuestos del 19% $${order.tax}</p>
                            <p> Tu total a pagar es de: <span class='numeros'>$${order.pagar}</span> </p>
                        </li>`
});
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Manipulacion de Array | Map </title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Karla:wght@200;400;600&display=swap" rel="stylesheet">
    <style>
        body{
            font-family: 'Karla', sans-serif;
            font-size: 18px;
        }
        .bill-container {
            margin: 0 auto;
            max-width: 70vw;
        }
        .bill-container ul {
            margin: 0;
            padding: 0;
            display: flex;
            flex-wrap: wrap;
            justify-content: center;
        }
        
        .bill--individual{
            margin: 40px 0;
            padding: 20px;
            min-width: 220px;
            max-width: 480px;
            list-style: none;
            background-color: rgb(234, 247, 232);
            border-radius: 20px;
        }

        .bill--individual .titulo{
            font-weight: 600;
        }
        .bill--individual .numeros{
            font-weight: 600;
            font-size: 20px;
        }
        .bill--individual .impuestos{
            font-weight: 200;
        }
            
        
    </style>
</head>
<body>
    <main>
        <section>
            <div class="bill-container">
                <ul id="bill">

                </ul>
            </div>
        </section>
    </main>
    <script src="./02Map.js"></script>
</body>
</html>

Excelente video y bien explicado

Wow! Cada clase quedo fascinado con cada tema nuevo que aprendo y el poder que tiene JS

SUPER interesante la clase. Gracias profe!

excelente clase!!

He visto y leído de varios conceptos como Spread Operators, la mutabilidad y como retornar los valores dentro de las funciones para que no produzcan efectos secundarios. Busque informacion dentro y fuera de platzi pero nunca me quedo tan claro como ahora. Excelente clase, excelente profe!

/* 
Tienes un array de productos con los siguientes atributos:
- name
- price
- stock
Debes agregar y calcular una nueva propiedad llamada "taxes", los impuestos deben ser del 19% con base al precio base.
Por ejemplo si aplicamos el 19% de impuestos para un producto con precio de $1000 el resultado de los "taxes" será $190, debes tener en cuenta que como resultado se debe dejar un valor entero sin decimales.
*/

function solution(array) {
	return array.map(x => ({
		...x,
		taxes: Math.trunc(array.price * .19)
	}))	 
}; 

Con este video pueden comprender un poco mejor que es lo que pasa con el str3 y porque es tan util:

https://www.youtube.com/watch?v=-Jt_86kUKuk

min 7.20 recordatorio, lo que pasa es que a la vuelta, digamos que pisa en la dirección de memoria del array y por lo tanto son iguales. por lo tanto si decimos que retorne otra cosa que no sea el item (el objeto completo), va a crear otro objeto y no pisar

Genial, dónde le doy like a está clase?

Incluso podríamos hacer validaciones para agregar propiedades al nuevo arreglo que no afectarían al original

   const show=document.querySelector(".showArray");

        const arreglo=[
            {Name:'peter',
             age:23,
             adress:'Av 23 Fort laudardale'},
             {Name:'jhon',
             age:18,
             adress:'32 Road'},
             {Name:'Mary',
             age:20,
             adress:'5 av, Fl'}
        ]
           arreglo.map(person=>{
               let futureAge=parseInt(person.age)+10;
            show.innerHTML+=`
            <div>
             <li>${'mi nombre es '+person.Name}</li>
             <li>${'y tengo '+person.age+' años de edad'}</li>
             <li>${'y en 10 años tendré '+futureAge+' años de edad'}</li>

             
           </div>    
           `
           })
           const arreglo2=arreglo.map((person)=>{
            if(person.adress.includes('Fl')){
                country="EE.UU"
            }else{
                country="Other"
            }
               return{
                   ...person,
                   
                   country
               }
           })
          
           console.log(arreglo)
           console.log(arreglo2)
    </script>

A ver si lo entendí correctamente, al utilizar el método map para generar un nuevo array copiamos la referencia en memoria, esto quiere decir que al tener un nuevo array y modificarlo estamos editando tanto el original como la copia porque nuestro nuevo array no copia los valores del objeto como tal, sino la referencia en memoria (que incluye todo el objeto) y por esa razón se modifican los dos arrays, mientras que con el spread operator lo que hacemos es copiarnos los valores directamente del objeto, por ende el array original no se verá afectado ya que el nuevo tiene copia de sus valores y se harán las modificaciones solo en ese.
Nose si estará bien mi forma de entender, o si alguien tiene una forma mas fácil de explicarla

Hola chic@s!
Me auto-reté a hacer esto en React xq lo tengo como objetivo de perfil profesional.

Comparto mi código:

import "./App.css";

function App() {
  const orders = [
    {
      customerName: "Nicolas",
      total: 60,
      delivered: true,
    },
    {
      customerName: "Zulema",
      total: 120,
      delivered: false,
    },
    {
      customerName: "Santiago",
      total: 180,
      delivered: true,
    },
    {
      customerName: "Valentina",
      total: 240,
      delivered: true,
    },
  ];

  const taxApply = (num) => {
    let tax = num * 0.19;
    return tax;
  };

  return (
    <div className="App">
      <header className="App-header">
        <h1>hola</h1>
        <ul>
          {orders &&
            orders.map((order) => (
              <li>
                <h4>{order.customerName}</h4>
                <h4>{order.total}</h4>
                <h4>{taxApply(order.total)}</h4>
              </li>
            ))}
        </ul>
      </header>
    </div>
  );
}

export default App;

asi renderiza:

No tenia ni idea sobre la referencia en memoria…

El concepto al que hace referencia el prfe sobre pulir los datos se le llama data mining y es todo un arte -> acá os dejo una clase al respecto

https://platzi.com/clases/1566-bd/19832-data-mining/

Excelente, no tenía ni idea que esto pasara.

Quiero compartirles esto, si usas el comando

console.table(array);

Tendras una visualización mejor de tus array.

Con console.log:

Con console.table

Hice el archivo HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>forEach</title>
  <style>
    body{
      width: 100%;
      background-color: blanchedalmond;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
    }
  </style>
</head>
<body>
    <div id="app"></div>
    <div id="app2"></div>

    <script>
      const app = document.getElementById('app');
      const app2 = document.getElementById('app2');
      const orders = [
        {
          customerName: "Nicolas",
          total: 60,
          delivered: true,
        },
        {
          customerName: "Zulema",
          total: 120,
          delivered: false,
        },
        {
          customerName: "Santiago",
          total: 180,
          delivered: true,
        },
        {
          customerName: "Valentina",
          total: 240,
          delivered: true,
        },
      ];

      //Este nos trae solo los valores que queremos en esta ocasion "total"
      const rta = orders.map(items => {
        return `<h1>${items.customerName} - ${items.total} - ${items.delivered}</h1>`
      })

      app.innerHTML = rta.join('')

      //Este solo modifica el nuevo array y el original lo deja como esta
      const rta2 = orders.map(items => {
        const obj = {
          ...items,
          tax: 0.19
        }
        return `<h1>${obj.customerName} - ${obj.total} - ${obj.delivered} - ${obj.tax}</h1>`
      });
      app2.innerHTML = rta2.join('')
    </script>
</body>
</html>

Muy útil esta clase 💪