Si usted está comenzando en JavaScript, tal vez usted no ha oído hablar de .map()
, .reduce()
y .filter()
., Para mí, me tomó un tiempo, ya que tuve que soportar Internet Explorer 8 hasta hace un par de años. Pero si no necesita ser compatible con este navegador muy antiguo, debe familiarizarse con esos métodos.
tenga en cuenta que este artículo probablemente se aplica a cualquier otro lenguaje de programación que pueda estar utilizando, ya que estos son conceptos que existen en muchos otros lenguajes.
permítanme explicar cómo funciona con un simple ejemplo. Supongamos que ha recibido una matriz que contiene varios objetos, cada uno representando a una persona., Lo que realmente necesita al final, sin embargo, es una matriz que contiene solo el id de cada persona.
Vamos a comparar!
Usando .forEach()
:
var officersIds = ;officers.forEach(function (officer) {
officersIds.push(officer.id);
});
Observe cómo se han de crear una matriz vacía de antemano? Vamos a ver cómo se ve al usar .map()
:
var officersIds = officers.map(function (officer) {
return officer.id
});
incluso podemos ser más concisos con las funciones de flecha (requiere soporte ES6, Babel o TypeScript)
const officersIds = officers.map(officer => officer.id);
760579af1a»> ¿trabajo?, Básicamente es Toma 2 argumentos, una devolución de llamada y un contexto opcional (se considerará como this
en la devolución de llamada) que no utilicé en el ejemplo anterior. La devolución de llamada se ejecuta para cada valor en la matriz y devuelve cada nuevo valor en la matriz resultante.
tenga en cuenta que la matriz resultante siempre tendrá la misma longitud que la matriz original.
.reduce ()
Al igual que .map()
, .reduce()
también ejecuta una devolución de llamada para cada elemento de una matriz., Lo que es diferente aquí es que reduce pasa el resultado de esta devolución de llamada (el acumulador) de un elemento de matriz al otro.
El acumulador puede ser casi cualquier cosa (entero, cadena, objeto, etc.) y debe ser instanciado o pasado al llamar a .reduce()
.
¡Es hora de un ejemplo! Digamos que tienes una matriz con estos pilotos y sus respectivos años de experiencia:
necesitamos conocer el total de años de experiencia de todos ellos., Con .reduce()
, es bastante sencillo:
var totalYears = pilots.reduce(function (accumulator, pilot) {
return accumulator + pilot.years;
}, 0);
observe que he establecido el valor inicial como 0. También podría haber utilizado una variable existente si fuera necesario. Después de ejecutar la devolución de llamada para cada elemento del array, reduce devolverá el valor final de nuestro acumulador (en nuestro caso: 82
).
veamos cómo se puede acortar esto con las funciones de flecha de ES6:
const totalYears = pilots.reduce((acc, pilot) => acc + pilot.years, 0);
Ahora digamos que quiero encontrar qué piloto es el más experimentado., Para eso, también puedo usar reducir:
var mostExpPilot = pilots.reduce(function (oldest, pilot) {
return (oldest.years || 0) > pilot.years ? oldest : pilot;
}, {});
nombré mi acumulador oldest
. Mi devolución de llamada compara el acumulador con cada piloto. Si un piloto tiene más años de experiencia que oldest
, entonces ese piloto se convierte en el nuevo oldest
por lo que es el que devuelvo.
como puede ver, usar .reduce()
es una forma fácil de generar un solo valor u objeto a partir de una matriz.
.filter()
¿Qué pasa si tienes una matriz, pero solo quieres algunos de los elementos en ella?, Ahí es donde .filter()
entra en juego!
Aquí están nuestros datos:
digamos que queremos dos arreglos ahora: uno para pilotos rebeldes, el otro para imperiales. Con .filter()
¡no podría ser más fácil!
Eso es todo! Y es aún más corto con las funciones de flecha:
const rebels = pilots.filter(pilot => pilot.faction === "Rebels");
const empire = pilots.filter(pilot => pilot.faction === "Empire");
Básicamente, si la función callback devuelve true, el elemento actual estará en la matriz resultante. Si devuelve false, no lo será.
combinando .asignar(), .reduce (), y .,filter ()
dado que los tres son llamados en arrays y desde .map()
y .filter()
ambos devuelven arrays, podemos encadenar fácilmente nuestras llamadas.
veamos otro ejemplo. Aquí están nuestros datos:
nuestro objetivo: obtener la puntuación total de usuarios de force solamente. ¡Hagámoslo paso a paso!
primero, necesitamos filtrar al personal que no puede usar la fuerza:
var jediPersonnel = personnel.filter(function (person) {
return person.isForceUser;
});// Result: (Luke, Ezra and Caleb)
con eso nos quedan 3 elementos en nuestro array resultante. Ahora Necesitamos crear una matriz que contenga la puntuación total de cada Jedi.,
var jediScores = jediPersonnel.map(function (jedi) {
return jedi.pilotingScore + jedi.shootingScore;
});// Result:
y vamos a usar reducir para obtener el total:
var totalJediScore = jediScores.reduce(function (acc, score) {
return acc + score;
}, 0);// Result: 420
y ahora aquí está la parte divertida can podemos encadenar todo esto para obtener lo que queremos en una sola línea:
y mira lo bonito que es con las funciones de flecha:
Boom! Note
Nota: en mi ejemplo anterior, .map()
y .filter()
ni siquiera eran necesarios. Podríamos lograr fácilmente el mismo resultado con solo .reduce()
. Los dejé ahí por el bien de este ejemplo., ¿Puede adivinar cómo solo pudimos mantener .reduce()
y obtener el mismo resultado con una línea de código? Ver la solución en CodePen
por qué no usar .forEach ()?
yo solía usar for
bucles en todas partes en lugar de .map()
, .reduce()
y .filter()
. Pero hace un par de años empecé a trabajar mucho más con datos que provenían de una API. Ahí es donde empecé a ver las ventajas de dejar .forEach
atrás.,
formateo
digamos que necesitas mostrar una lista de personas, con su nombre y título de trabajo.
var data =
la API le da los datos anteriores, pero solo necesita el título y el apellido de cada persona… necesita formatear los datos. Sin embargo, tu aplicación también debe tener una vista única para cada persona, por lo que debes escribir una función de formato de datos que funcione tanto en una vista de Lista como en una vista única.,
eso significa que no puede tener el bucle .forEach
dentro de su función de formato, o de lo contrario tendría que envolver su elemento individual en una matriz antes de pasarlo a la función solo para que funcione, de esta manera:
var result = formatElement();
// Yeah... that's not right at all
así que su bucle tiene que envolver la llamada de la función, de esta manera:
data.forEach(function (element) {
var formatted = formatElement(element);
// But what then....
});
pero .forEach()
no devuelve nada. Eso significa que tienes que empujar los resultados dentro de una matriz predeterminada.,
var results = ;data.forEach(function (element) {
var formatted = formatElement(element);
results.push(formatted);
});
como resultado, tiene 2 Funciones: su función formatElement()
y su función que envía los resultados a su matriz.
¿Por qué tener 2 funciones cuando puedes tener solo una?
var results = data.map(formatElement);
las pruebas son más fáciles
si escribes pruebas unitarias para tu código, te resultará más sencillo probar las funciones que llamas con .map()
, .reduce()
, o .filter()
.
todo lo que tiene que hacer es proporcionar datos entrantes para la función y esperar que salga un resultado., Básicamente «¿qué sale si esto se pasa?”. Menos manipulación, menos beforeEach()
y afterEach()
s). Es sencillo, simple prueba.
¡pruébalo!
si te gustó ese artículo y quieres aprender más métodos de matriz, echa un vistazo a mi artículo sobre cómo usar .some()
y .find()
en JavaScript.
¡sigue codificando!