Introducción
Tu AS bajo la manga
Fundamentos del manejo de arrays
ForEach
Mutable o Inmutable
Map
Desafío: Todos los elementos por dos usando map.
Map Reloaded
Desafío: Agrega la propiedad.
Filter
Desafío: Filtra las palabras de 4 letras y más.
Reduce
Desafío: Calcula el total de un array.
Reduce Reloaded
Métodos en JavaScript
Some
Desafío: ¿Existe algún par?
Every
Desafío: ¿Todos son pares?
Find y FindIndex
Includes
Desafío: Crea un buscador
Join
Desafío: Construye una URL
Concat
Flat
FlatMap
Mutable functions
Sort
Despedida
Despedida
Aún no tienes acceso a esta clase
Crea una cuenta y continúa viendo este curso
Aportes 35
Preguntas 2
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.
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.
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);
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
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.
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;
}
Que joyita de clase 😮😮
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
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;
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
No tenia ni idea sobre la referencia en memoria…
Sacha Lifsyc https://www.youtube.com/watch?v=tP8JiVUiyDo&t=634s
Hector de Leon , Intro a la programacion funcional
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
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.
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 💪
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 ]
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;
});
¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.