10 funciones importantes de Lodash para desarrolladores de JavaScript

Para los desarrolladores de JavaScript, Lodash no necesita presentación. Sin embargo, la biblioteca es enorme y, a menudo, se siente abrumadora. ¡Ya no!
Lodash, Lodash, Lodash. . . ¡Por dónde empiezo! 🤔
Hubo un tiempo en que JavaScript ecosel sistema era incipiente; Podría compararse con el salvaje oeste o una jungla, por así decirlo, donde sucedían muchas cosas, pero había muy pocas respuestas para las frustraciones y la productividad cotidianas de los desarrolladores.
Entonces Lodash entró en escena, y se sintió como una inundación que lo sumergió todo. Desde las necesidades cotidianas simples como la clasificación hasta las transformaciones complejas de la estructura de datos, Lodash vino cargado (¡sobrecargado, incluso!) Con una funcionalidad que convirtió la vida de los desarrolladores de JS en una pura felicidad.

¿Y dónde está Lodash hoy? Bueno, todavía tiene todas las ventajas que ofrecía inicialmente.ally, y algo más, pero parece haber perdido participación en la comunidad de JavaScript. ¿Por qué? Puedo pensar en algunas razones:
- Algunas funciones de la biblioteca Lodash eran (y siguen siendo) lentas cuando se aplican a listas grandes. Si bien esto nunca habría afectado al 95% de los proyectos, los desarrolladores influyentes del 5% restante le dieron a Lodash una mala prensa y el efecto se extendió a las bases.
- Hay una tendencia en el JS. ecossistema (incluso podría decir lo mismo de la gente de Golang) donde la arrogancia es más común de lo necesario. Por lo tanto, confiar en algo como Lodash se considera estúpido y es rechazado en foros como StackOverflow cuando la gente sugiere este tipo de soluciones (“¡¿Qué?! ¿Usar una biblioteca completa para algo como esto? Puedo combinar
filter()
reduce()
para lograr lo mismo en una función simple! ”). - Lodash es viejo. Al menos según los estándares de JS. Salió en 2012, así que hasta el momento de escribirlo, han pasado casi diez años. los API ha sido estable y no se pueden agregar muchas cosas interesantes cada año (simplemente porque no es necesario), lo que generaateEs el aburrimiento para el desarrollador JS promedio sobreexcitado.
En mi opinión, no usar Lodash es una pérdida significativa para nuestro JavaScript bases de código. Ha probado soluciones elegantes y libres de errores para los problemas cotidianos con los que nos encontramos en el trabajo, y su uso solo hará que nuestro código sea más legible y fácil de mantener.
Dicho esto, profundicemos en algunas de las funciones comunes (¡o no!) de Lodash y veamos cuán increíblemente útiles y beautiful esta biblioteca es.
Clonar. . . deeply!
Dado que los objetos se pasan por referencia en JavaScript, creaateEs un dolor de cabeza para los desarrolladores cuando quieren clonar algo con la esperanza de que el nuevo conjunto de datos sea diferente.
let people = [
{
name: 'Arnold',
specialization: 'C++',
},
{
name: 'Phil',
specialization: 'Python',
},
{
name: 'Percy',
specialization: 'JS',
},
];
// Find people writing in C++
let folksDoingCpp = people.filter((person) => person.specialization == 'C++');
// Convert them to JS!
for (person of folksDoingCpp) {
person.specialization = 'JS';
}
console.log(folksDoingCpp);
// [ { name: 'Arnold', specialization: 'JS' } ]
console.log(people);
/*
[
{ name: 'Arnold', specialization: 'JS' },
{ name: 'Phil', specialization: 'Python' },
{ name: 'Percy', specialization: 'JS' }
]
*/
Nótese cómo en nuestra pura inocencia y a pesar de nuestras buenas intenciones, el original people
matriz mutated en el process (La especialización de Arnold cambió de C++
a JS
) - ¡un gran golpe para la integridad del sistema de software subyacente! De hecho, necesitamos una forma de hacer una copia verdadera (profunda) de la matriz original.

Quizás se pueda argumentar que esta es una forma "tonta" de codificar en JS; sin embargo, la realidad es una bit cómpliceated. Sí, tenemos disponible el encantador operador de desestructuración, pero cualquiera que haya intentado desestructurar objetos y matrices complejos conoce el problema. Luego, está la idea de usar serialización y deserialización (quizás JSON) para lograr una copia profunda, pero solo hace que su código sea más complicado para el lector.
Por el contrario, mire lo increíblemente elegante y concisa que es la solución cuando se acostumbra a Lodash:
const _ = require('lodash');
let people = [
{
name: 'Arnold',
specialization: 'C++',
},
{
name: 'Phil',
specialization: 'Python',
},
{
name: 'Percy',
specialization: 'JS',
},
];
let peopleCopy = _.cloneDeep(people);
// Find people writing in C++
let folksDoingCpp = peopleCopy.filter(
(person) => person.specialization == 'C++'
);
// Convert them to JS!
for (person of folksDoingCpp) {
person.specialization = 'JS';
}
console.log(folksDoingCpp);
// [ { name: 'Arnold', specialization: 'JS' } ]
console.log(people);
/*
[
{ name: 'Arnold', specialization: 'C++' },
{ name: 'Phil', specialization: 'Python' },
{ name: 'Percy', specialization: 'JS' }
]
*/
Note como el people
matriz está intacta después de la clonación profunda (Arnold todavía se especializa en C++
en este caso). Pero lo que es más importante, el código es sencillo de entender.
Eliminar duplicadosates de una matriz
Eliminando duplicadosates de una matriz suena como un excelente problema de entrevista/pizarra (recuerde, en caso de duda, ¡arroje un mapa hash al problema!). Y, por supuesto, siempre puedes escribir una función personalizada para hacer eso, pero ¿qué pasa si te encuentras con varios escenarios diferentes en los que hacer que tus matrices sean únicas? Podrías escribir varios otras funciones para eso (y arriesgarse a encontrar errores sutiles), ¡o simplemente podría usar Lodash!
Nuestro primer ejemplo de matrices únicas es bastante trivial, pero aún representa la velocidad y confiabilidad que Lodash aporta. Imagine hacer esto escribiendo toda la lógica personalizada que suself!
const _ = require('lodash');
const userIds = [12, 13, 14, 12, 5, 34, 11, 12];
const uniqueUserIds = _.uniq(userIds);
console.log(uniqueUserIds);
// [ 12, 13, 14, 5, 34, 11 ]
Observe que la matriz final no está ordenada, lo cual, por supuesto, no es motivo de preocupación aquí. Pero ahora imaginemos una situación más complicada.ateEscenario d: tenemos una serie de usuarios que extrajimos de algún lugar, pero queremos asegurarnos de que contenga solo usuarios únicos. ¡Fácil con Lodash!
const _ = require('lodash');
const users = [
{ id: 10, name: 'Phil', age: 32 },
{ id: 8, name: 'Jason', age: 44 },
{ id: 11, name: 'Rye', age: 28 },
{ id: 10, name: 'Phil', age: 32 },
];
const uniqueUsers = _.uniqBy(users, 'id');
console.log(uniqueUsers);
/*
[
{ id: 10, name: 'Phil', age: 32 },
{ id: 8, name: 'Jason', age: 44 },
{ id: 11, name: 'Rye', age: 28 }
]
*/
En este ejemplo, usamos el uniqBy()
método para decirle a Lodash que queremos que los objetos sean únicos en el id
propiedad. En una línea, expresamos lo que podría haber tomado de 10 a 20 líneas e introducido más posibilidades de errores.
Hay muchas más cosas disponibles para hacer que las cosas sean únicas en Lodash, y te animo a que eches un vistazo a documentos.
Diferencia de dos matrices
Unión, diferencia, etc., pueden parecer términos que es mejor dejar atrás en las aburridas conferencias de la escuela secundaria sobre teoría de conjuntos, pero aparecen con mayor frecuencia en la práctica diaria. Es común tener una lista y querer fusionar otra lista con ella o querer encontrar qué elementos son exclusivos de ella en comparación con otra lista; para estos escenarios, la función de diferencia es perfecta.

Comencemos el viaje de la diferencia tomando un escenario simple: ha recibido una lista de todos los identificadores de usuario en el sistema, así como una lista de aquellos cuyas cuentas están activas. ¿Cómo encuentras los identificadores inactivos? Simple, ¿verdad?
const _ = require('lodash');
const allUserIds = [1, 3, 4, 2, 10, 22, 11, 8];
const activeUserIds = [1, 4, 22, 11, 8];
const inactiveUserIds = _.difference(allUserIds, activeUserIds);
console.log(inactiveUserIds);
// [ 3, 2, 10 ]
¿Y qué pasa si, como sucede en un entorno más realista, tienes que trabajar con una serie de objetos en lugar de simples primitivos? Bueno, Lodash tiene un nice differenceBy()
método para esto!
const allUsers = [
{ id: 1, name: 'Phil' },
{ id: 2, name: 'John' },
{ id: 3, name: 'Rogg' },
];
const activeUsers = [
{ id: 1, name: 'Phil' },
{ id: 2, name: 'John' },
];
const inactiveUsers = _.differenceBy(allUsers, activeUsers, 'id');
console.log(inactiveUsers);
// [ { id: 3, name: 'Rogg' } ]
¡¿Limpio, verdad ?!
Como diferencia, hay otros métodos en Lodash para operaciones de conjuntos comunes: unión, intersección, etc.
Aplanamiento de matrices
La necesidad de aplanar matricesriseEs bastante frecuente. Un caso de uso es que haya recibido una respuesta de API y necesite aplicar algunas map()
y filter()
combo en una lista compleja de objetos / matrices anidadas para extraer, digamos, identificadores de usuario, y ahora te quedan matrices de matrices. Aquí hay un fragmento de código que describe esta situación:
const orderData = {
internal: [
{ userId: 1, date: '2021-09-09', amount: 230.0, type: 'prepaid' },
{ userId: 2, date: '2021-07-07', amount: 130.0, type: 'prepaid' },
],
external: [
{ userId: 3, date: '2021-08-08', amount: 30.0, type: 'postpaid' },
{ userId: 4, date: '2021-06-06', amount: 330.0, type: 'postpaid' },
],
};
// find user ids that placed postpaid orders (internal or external)
const postpaidUserIds = [];
for (const [orderType, orders] of Object.entries(orderData)) {
postpaidUserIds.push(orders.filter((order) => order.type === 'postpaid'));
}
console.log(postpaidUserIds);
Puedes adivinar que postPaidUserIds
ahora parece? Pista: ¡es repugnante!
[
[],
[
{ userId: 3, date: '2021-08-08', amount: 30, type: 'postpaid' },
{ userId: 4, date: '2021-06-06', amount: 330, type: 'postpaid' }
]
]
Ahora bien, si eres una persona sensata, no querrás escribir lógica personalizada para extract los objetos del pedido y distribúyalos nicely en una fila dentro de una matriz. Sólo usa el flatten()
método y disfruta de las uvas:
const flatUserIds = _.flatten(postpaidUserIds);
console.log(flatUserIds);
/*
[
{ userId: 3, date: '2021-08-08', amount: 30, type: 'postpaid' },
{ userId: 4, date: '2021-06-06', amount: 330, type: 'postpaid' }
]
*/
Tenga en cuenta que flatten()
solo llega a un nivel de profundidad. Es decir, si sus objetos están atascados a dos, tres o más niveles de profundidad, flatten()
te decepcionarán. En esos casos, Lodash tiene la flattenDeep()
método, pero tenga en cuenta que la aplicación de este método en estructuras muy grandes puede ralentizar las cosas (ya que detrás de escena, hay una operación recursiva en el trabajo).
¿Está vacío el objeto/matriz?
Gracias a cómo funcionan los valores y tipos "falsos" en JavaScript, a veces algo tan simple como verificar el vacío resulta en pavor existencial.
¿Cómo se comprueba si una matriz está vacía? Puede comprobar si es length
is 0
o no. Ahora, ¿cómo se comprueba si un objeto está vacío? Bueno… ¡espera un minuto! Aquí es donde ese sentimiento de inquietud conjuntos en, y esos ejemplos de JavaScript que contienen cosas como [] == false
y {} == false
empezar a dar vueltas en nuestras cabezas. Cuando está bajo presión para ofrecer una función, las minas terrestres como estas son lo último que necesita: harán que su código sea difícil de entender e introducirán incertidumbre en su conjunto de pruebas.
Trabajar con datos faltantes
En el mundo real, los datos nos escuchan; No importa lo mucho que lo deseemos, rara vez es racionalizado y cuerdo. Un ejemplo típico es la falta de objetos / matrices nulos en una gran estructura de datos recibida como respuesta de la API.
Supongamos que recibimos el siguiente objeto como respuesta de la API:
const apiResponse = {
id: 33467,
paymentRefernce: 'AEE3356T68',
// `order` object missing
processedAt: `2021-10-10 00:00:00`,
};
Como se muestra, generamosally obtener una order
Objeto en la respuesta de la API, pero no siempre es así. Entonces, ¿qué pasa si tenemos algún código que se basa en este objeto? Una forma sería codificar a la defensiva, pero dependiendo de qué tan anidado order
El objeto es que pronto estaremos escribiendo un código muy feo si deseamos evitar errores en tiempo de ejecución:
if (
apiResponse.order &&
apiResponse.order.payee &&
apiResponse.order.payee.address
) {
console.log(
'The order was sent to the zip code: ' +
apiResponse.order.payee.address.zipCode
);
}
🤢🤢 Sí, muy feo de escribir, muy feo de leer, muy feo de mantener, etc. Afortunadamente, Lodash tiene una forma sencilla de lidiar con tales situaciones.
const zipCode = _.get(apiResponse, 'order.payee.address.zipCode');
console.log('The order was sent to the zip code: ' + zipCode);
// The order was sent to the zip code: undefined
También existe la fantástica opción de proporcionar un valor predeterminado en lugar de obtener undefined
por faltar cosas:
const zipCode2 = _.get(apiResponse, 'order.payee.address.zipCode', 'NA');
console.log('The order was sent to the zip code: ' + zipCode2);
// The order was sent to the zip code: NA
No se tu pero get()
es una de esas cosas que me hacen llorar de felicidad. No es nada llamativo. No hay sintaxis consultada ni opciones para memorizar, pero mira la cantidad de sufrimiento colectivo que puede aliviar.ate! 😇
Rebotando
En caso de que no lo sepas, la eliminación de rebotes es un tema común en el desarrollo frontend. La idea es que a veces es beneficioso lanzar una acción no de inmediato.ately pero después de algún tiempo (generalmenteally, unos milisegundos). ¿Qué significa eso? He aquí un ejemplo.
Imagine un sitio web de comercio electrónico con una barra de búsqueda (bueno, ¡cualquier sitio web/aplicación web hoy en día!). Para una mejor experiencia de usuario, no queremos que el usuario tenga que presionar Intro (o peor aún, presionar el botón "buscar") para mostrar sugerencias.revVistas basadas en su término de búsqueda. Pero la respuesta obvia es una bit cargado: si agregamos un detector de eventos a onChange()
para la barra de búsqueda y lanzar una llamada API por cada pulsación de tecla, tendríamos createuna pesadilla para nuestro backend; Habría demasiadas llamadas innecesarias (por ejemplo, si se busca “cepillo de alfombra blanca”, ¡habrá un total de 18 solicitudes!) y casi todas serán irrelevantes porque la entrada del usuario no ha terminado.
La respuesta está en la eliminación de rebotes, y la idea es la siguiente: no envíe una llamada a la API tan pronto como cambie el texto. Espere un tiempo (digamos, 200 milisegundos) y si en ese momento hay otra pulsación de tecla, cancele el conteo de tiempo anterior y vuelva a comenzar a esperar. Como resultado, es solo cuando el usuario hace una pausa (ya sea porque está pensando o porque ha terminado y espera alguna respuesta) que enviamos una solicitud de API al backend.
La cadena generalategy que describí es cómpliceated, y no me sumergiré en el synccronización de la gestión y cancelación del cronómetro; sin embargo, el rebote real process Es muy simple si estás usando Lodash.
const _ = require('lodash');
const axios = require('axios');
// This is a real dogs' API, by the way!
const fetchDogBreeds = () =>
axios
.get('https://dog.ceo/api/breeds/list/all')
.then((res) => console.log(res.data));
const debouncedFetchDogBreeds = _.debounce(fetchDogBreeds, 1000); // after one second
debouncedFetchDogBreeds(); // shows data after some time
Si estas pensando setTimeout()
Yo hubiera hecho el mismo trabajo, bueno, ¡hay más! Lodash debounce viene con muchas funciones potentes; por ejemplo, es posible que desee asegurarse de que debounce no es indefinido. Es decir, incluso si se pulsa una tecla cada vez que la función está a punto de activarse (cancelando así la función general). process), es posible que desee asegurarse de que la llamada a la API se realice de todos modos después de, digamos, dos segundos. Para esto, Lodash debounce()
tiene la maxWait
opción:
const debouncedFetchDogBreeds = _.debounce(fetchDogBreeds, 150, { maxWait: 2000 }); // debounce for 250ms, but send the API request after 2 seconds anyway
Echa un vistazo al oficial documentos para una inmersión más profunda. ¡Están llenos de cosas súper importantes!
Eliminar valores de una matriz
No sé ustedes, pero yo hate escribir código para eliminar elementos de una matriz. Primero, tengo que obtener el índice del elemento y verificar si el índice es real.ally válido y si es así, llame al splice()
método, y así sucesivamente. Nunca puedo recordar la sintaxis y, por lo tanto, necesito buscar las cosas todo el tiempo, y al final, me quedo con la molesta sensación de que he dejado que un error estúpido se cuele.
const greetings = ['hello', 'hi', 'hey', 'wave', 'hi'];
_.pull(greetings, 'wave', 'hi');
console.log(greetings);
// [ 'hello', 'hey' ]
Tenga en cuenta dos cosas:
- La matriz original se cambió en el process.
- La
pull()
El método elimina todas las instancias, incluso si hay duplicados.ates.
Hay otro relatemétodo d llamado pullAll()
que acepta una matriz como segundo parámetro, lo que facilita la eliminación de varios elementos a la vez. Concedido que podríamos usar pull()
con un operador de propagación, pero recuerde que Lodash llegó en un momento en que el operador de propagación ni siquiera era una propuesta en el idioma.
const greetings2 = ['hello', 'hi', 'hey', 'wave', 'hi'];
_.pullAll(greetings2, ['wave', 'hi']);
console.log(greetings2);
// [ 'hello', 'hey' ]
Último índice de un elemento
Nativo de JavsScript indexOf()
¡El método es genial, excepto cuando está interesado en escanear la matriz desde la dirección opuesta! Y una vez más, sí, podría simplemente escribir un bucle decreciente y encontrar el elemento, pero ¿por qué no usar una técnica mucho más elegante?
Aquí hay una solución rápida de Lodash usando el lastIndexOf()
método:
const integers = [2, 4, 1, 6, -1, 10, 3, -1, 7];
const index = _.lastIndexOf(integers, -1);
console.log(index); // 7
Unfortunately, no existe ninguna variante de este método en la que podamos buscar objetos complejos o incluso pasar una función de búsqueda personalizada.
Cremallera. ¡Abrir la cremallera!
A menos que hayas trabajado en Python, zip/unzip es una utilidad que quizás nunca notes o imagines en toda tu carrera como desarrollador de JavaScript. Y tal vez por una buena razón: rara vez existe el tipo de desperate necesidad de comprimir/descomprimir como hay para filter()
, etc. Sin embargo, es una de las mejores utilidades menos conocidas que existen y puede ayudarle a crearate código sucinto en algunas situaciones.
Al contrario de lo que parece, zip / unzip no tiene nada que ver con la compresión. En cambio, es una operación de agrupación donde las matrices de la misma longitud se pueden convertir en una única matriz de matrices con elementos en la misma posición empaquetados juntos (zip()
) y de regreso (unzip()
). Sí, lo sé, se está volviendo confuso tratar de arreglárselas con palabras, así que veamos un código:
const animals = ['duck', 'sheep'];
const sizes = ['small', 'large'];
const weight = ['less', 'more'];
const groupedAnimals = _.zip(animals, sizes, weight);
console.log(groupedAnimals);
// [ [ 'duck', 'small', 'less' ], [ 'sheep', 'large', 'more' ] ]
Las tres matrices originales se convirtieron en una sola con dos matrices solamente. Y cada una de estas nuevas matrices representa un único animaTengo todo en un solo lugar. Entonces, el índice 0
nos dice ese tipo de animalo es, el índice 1
nos dice su tamaño y el índice 2
nos dice su peso. Como resultado, ahora es más fácil trabajar con los datos. Una vez que hayas aplicado whateVer las operaciones que necesita en los datos, puede dividirlos nuevamente usando unzip()
y envíelo de vuelta a la fuente original:
const animalData = _.unzip(groupedAnimals);
console.log(animalData);
// [ [ 'duck', 'sheep' ], [ 'small', 'large' ], [ 'less', 'more' ] ]
La utilidad zip / unzip no es algo que cambiará tu vida de la noche a la mañana, ¡pero cambiará tu vida algún día!
Para Concluir 👨🏫
(Pongo todo el código fuente usado en este artículo Haga clic aquí para entrar. para que lo pruebes directamente desde la brows¡Eh!)
El Lodash documentos están repletos de ejemplos y funciones que te dejarán boquiabierto. En una época en la que el masoquismo parece estar aumentando en JS ecossistema, Lodash es como un soplo de aire fresco y le recomiendo encarecidamente que utilice esta biblioteca en sus proyectos.