Cuatro API integradas de JavaScript que reemplazan a los auxiliares comunes de Lodash
Cómo Math.sumPrecise, Map getOrInsert, Array.fromAsync y los auxiliares de iterador reemplazan las utilidades de Lodash, además de las consideraciones sobre precisión y concurrencia que es necesario conocer.
Instalar Lodash solía ser uno de los primeros pasos en cualquier proyecto JavaScript: sumaba números, llenaba mapas con valores por defecto y permitía realizar transformaciones de forma secuencial. Las versiones recientes de ECMAScript incluyen equivalentes integrados para estas tareas, por lo que la dependencia a menudo representa solo un aumento en el tamaño del paquete. A continuación se presentan cuatro API nativas, qué reemplazan y en qué casos la explicación habitual de una sola línea resulta engañosa.
El soporte de los motores para estas adiciones recientes aún se está implementando, por lo que consulte los datos de compatibilidad de sus navegadores y versión de Node.js antes de utilizar un polyfill. Para un estudio más amplio, consulte siete características nativas de JavaScript que reemplazan las dependencias de utilidades.
Math.sumPrecise() en lugar de _.sum()
Los números en JavaScript son de tipo doble IEEE 754, y por eso 0.1 + 0.2 da como resultado 0.30000000000000004. _.sum() no ofrece ninguna protección: se trata de un simple bucle con operación +, por lo que hereda todos los pasos de redondeo. Math.sumPrecise() toma un iterable y devuelve la suma como si se hubiera calculado con precisión, redondeando una sola vez al final.
// ❌ The Legacy Lodash/Hack Way
const prices = [0.1, 0.2];
const total = _.sum(prices); // Still prone to precision errors without custom logic
// ✅ The ES2026 Native Standard
const exactTotal = Math.sumPrecise([0.1, 0.2]);
console.log(exactTotal); // 0.3 (Perfect precision)
Una corrección al comentario anterior: 0.1 y 0.2 ya son inexactos antes de cualquier suma, y su suma exacta redondea a 0.30000000000000004; por lo tanto, Math.sumPrecise([0.1, 0.2]) devuelve ese valor y no 0.3. Lo que hace este método es eliminar el error acumulado en múltiples sumas: para [1e20, 0.1, -1e20], la suma simple da como resultado 0, mientras que Math.sumPrecise devuelve 0.1. Dado que no se trata de un tipo decimal, el dinero debe representarse en centavos enteros o mediante una biblioteca de tipos decimales. Además, lanza un TypeError ante valores que no son numéricos en lugar de forzar su conversión.
Map.prototype.getOrInsert() en lugar de has/set/get
Los auxiliares de caché y agrupación siguen un patrón familiar: se verifica si existe una clave, se almacena un valor por defecto si falta, y luego se lee el valor correspondiente. getOrInsert(key, defaultValue) realiza todo esto en una sola llamada, devolviendo la entrada existente o insertando y devolviendo el valor por defecto.
// ❌ The Legacy Way
const userCache = new Map();
function getUser(id) {
if (!userCache.has(id)) {
userCache.set(id, { status: 'pending' });
}
return userCache.get(id);
}
// ✅ The ES2026 Native Standard
const userCache = new Map();
function getUser(id) {
// Checks for the key. If missing, inserts the fallback and returns it instantly.
return userCache.getOrInsert(id, { status: 'pending' });
}
Tenga en cuenta que el objeto de respaldo sigue siendo creado en cada llamada, incluso cuando se descarta. Si el valor por defecto es costoso, utilice getOrInsertComputed(key, callback), que ejecuta la función de callback solo cuando no se encuentra la clave. Ambos métodos también existen en WeakMap; el aspecto relacionado con Node.js se explica en Node.js 26: Temporal, Map upserts y Undici 8.
Array.fromAsync() para agotar iterables asíncronos
Recopilar un cliente de API paginado o una secuencia legible en un array solía significar utilizar un bucle for await...of escrito a mano para insertar los elementos en un acumulador. Array.fromAsync() consume un iterable asíncrono, espera a que se procesen cada uno de sus elementos y devuelve un array normal.
// The ES2026 Native Standard
async function fetchAllPages(asyncPaginationStream) {
// Consumes the entire async stream and resolves into a flat array
const allRecords = await Array.fromAsync(asyncPaginationStream);
return allRecords;
}
Un segundo argumento opcional permite mapear cada elemento, y también se espera su resultado, lo que abarca el caso del método map asíncrono. Tenga en cuenta que los elementos se procesan de forma secuencial, en orden. Esto es adecuado para flujos y cursores, pero no sustituye a Promise.all: si tiene promesas independientes que deben ejecutarse de forma concurrente, Promise.all sigue siendo la herramienta adecuada. Además, almacenar en memoria un flujo ilimitado anula el propósito de trabajar con flujos.
Ayudas de iterador en lugar de _.chain()
La razón más importante para seguir utilizando Lodash ha sido _.chain(), cuya evaluación perezosa permite que operaciones como map, filter y take-five sobre 10,000 elementos dejen de ejecutarse una vez que existen cinco resultados. Los métodos de array, en cambio, son agresivos: .map() crea un array intermedio completo, .filter() lo recorre nuevamente y .slice() descarta la mayor parte del trabajo realizado.
Los auxiliares de iterador, estandarizados en ES2025, permiten esta evaluación perezosa de forma nativa. .values() devuelve un iterador, y map, filter y take sobre él obtienen un elemento a la vez hasta que toArray() recopila el resultado final.
// ❌ The Array Way (Inefficient: Maps and filters all 10,000 items)
const result = massiveArray
.map(x => heavyComputation(x))
.filter(x => x > 100)
.slice(0, 5);
// ✅ The ES2026 Native Lazy Standard
const result = massiveArray
.values() // Converts to an Iterator
.map(x => heavyComputation(x))
.filter(x => x > 100)
.take(5) // Stops exactly when 5 items are found!
.toArray();
Cada elemento pasa por todo el pipeline antes de que se solicite el siguiente, por lo que heavyComputation solo se ejecuta hasta que se encuentran cinco coincidencias. Compromisos: los iteradores son de un solo uso, no existe una función sort o reverse perezosa, y para arrays pequeños los métodos inmediatos son igual de rápidos y fáciles de depurar.
Puntos clave
Math.sumPrecise()elimina el error de redondeo acumulado pero no puede corregir entradas inexactas; use centavos enteros para monedas.getOrInsert()reemplaza a has/set/get; prefieragetOrInsertComputed()para valores por defecto costosos.Array.fromAsync()procesa los iterables asíncronos de forma secuencial; utilicePromise.allpara lograr concurrencia..values()junto con los auxiliares de iterador proporcionan pipelines perezosos similares a_.chain()sin depender de ninguna librería externa.
Lecturas relacionadas
- Auditoría de utils.js: Seis funciones integradas que reemplazan a los auxiliares manuales — Descubra qué APIs nativas de JavaScript pueden sustituir a los métodos manuales para clonar profundamente, hacer copias defensivas, gestionar tiempos de espera, manejar promesas diferidas y usar lodash groupBy, así como qué consideraciones son aplicables.
- Métodos modernos de array en JavaScript que reemplazan a los patrones comunes — Aprenda cómo métodos más recientes de array en JavaScript como groupBy, toSorted, with y findLast reemplazan a soluciones verbosas basadas en reduce, spread y reverse.