Introducción
Tu AS bajo la manga
Fundamentos del manejo de arrays
ForEach
Mutable o Inmutable
Qué es el método map
Playground: multiplica todos los elementos por dos
Map Reloaded
Playground: calcula y agrega nuevas propiedades a un array
Filter
Playground: retorna solo palabras de 4 letras o más
Reduce
Reduce Reloaded
Playground: calcula la suma total de elementos en un array
Métodos en JavaScript
Some
Playground: ¿al menos 1 de los números es par?
Every
Playground: retorna un booleano si todos los elementos son pares
Find y FindIndex
Includes
Playground: buscador de palabras con parámetros de búsqueda
Join
Playground: construye URLs a partir de strings
Concat
Flat
FlatMap
Playground: calcula el total de palabras en un texto
Mutable functions
Sort
Despedida
Despedida
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Nicolas Molina
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,
},
]
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 ]
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 63
Preguntas 8
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:
.
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);
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.
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
Los navegadores web usan dos tipos de memorias: Stack y Heap.
Es veloz, pero sin tanto espacio.
Aquí se guardan los valores primitivos (booleanos, strings, números…).
Es más lenta, pero permite guardar enormes cantidades de información.
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);
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
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
Que joyita de clase 😮😮
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.
Sacha Lifsyc https://www.youtube.com/watch?v=tP8JiVUiyDo&t=634s
Hector de Leon , Intro a la programacion funcional
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
};
});
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
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;
}
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
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:
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
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;
No tenia ni idea sobre la referencia en memoria…
Excelente, no tenía ni idea que esto pasara.
Para entender mejor el
spread operator …item,
https://platzi.com/clases/1815-ecmascript-6/26122-let-y-const-multilinea-spread-operator-y-desestruc/
min: 7:50
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 💪
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?