Чатыры вбудованыя API JavaScript, якія заменяюць популярныя функцыі Lodash
Як Math.sumPrecise, Map.getOrInsert, Array.fromAsync і падчырнікі-памагчыцы заменяюць функцыі Lodash, а таксама якія є аспекты точнасці і паралельнай обработкі, якія трэба ведаць.
Установка Lodash ранейш чырвоным крокам у будзь-ям проекте на JavaScript: ён сумаваў лікі, запалняў карты стандартнымі значэннямі і выканаў ляжлівыя трансфармацыі. Няўзгоднае выданні ECMAScript ужо мае вбудованыя аналогі для гэтых задач, таму такая залежнасць часта ёст толькі дадатковым вагам пакета. Ёсць чатыры вбудованыя API, што яны заменяюць, і дзе звычныя однай-лінейныя адказы пра іх ёсць падвядомымі.
Падтрымка гэтых новых функцыяй у двойчыку ўсё яшчэ розвіваецца, таму пераканайцеся ў данных пра сумяшчальнасць вашых браузераў і версіі Node.js пры выборы поліфіла. Для болей шырокага аптэксту, пазірце семь вбудованых функцыяй JavaScript, якія заменяюць залежнасці ад утиліт.
Math.sumPrecise() замест _.sum()
Чысла ў JavaScript являюцься значэннямі типу IEEE 754 doubles, таму 0.1 + 0.2 дае 0.30000000000000004. Функцыя _.sum() не забезпечвае ніякай захопнай працы: гэта звычны цикл з аператарам +, таму ён перадае всі наследаваны эфекты заокруглення. Функцыя Math.sumPrecise() прыме які-небудзь ітерабельны об’ект і вярне суму так, як будзе вырахована абсолютна точна, заокругліваючы ў канцы.
// ❌ 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)
Адзін выправлення да асаблівы ўжо вышэй: 0.1 і 0.2 ўжо неясныя яшчэ до будзь-якага дадавання, а ўсё іх точнае сума прагружваецца да 0.30000000000000004, таму Math.sumPrecise([0.1, 0.2]) вяртае гэтую значэнне, а не 0.3. Тое, што гэты метод усуняе, — это паклопыткі, якія накапляюцца пасля багатых дадаванняў: для [1e20, 0.1, -1e20] простае дадаванне дае 0, тады калі Math.sumPrecise вяртае 0.1. Гэта не тип дзесятковых чисоў, таму грошы все рава трэба хаваць у целых сэнтах або ў бібліятэцы дзесятковых чисоў. Ён таксама выклікае TypeError для нечыслаў, у замест на тое, каб іх прымусова пераканструюваць.
Map.prototype.getOrInsert() замест has/set/get
Кэшы і адпраменты для групавання выконваюць аднаковую схему: пераглядаецца ключ, якщо ён не існуе, зберагаецца значэнне за замовчанням, а пасля чытаецца сама цянь. getOrInsert(key, defaultValue) выконвае все гэта за адну вызов, вяртаючы існуючую ентрыту або ствараючы новую і вяртаючы значэнне за замовчанням.
// ❌ 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' });
}
Заўважыце, што об’ект для альтернатывнага выкарыстоўвання все равно ствараецца за кожны вызов, нават калі ён пазьней не выкарыстоўваецца. Якщо значэнне за замовчанням є ресурсоўна выкарыстоўваным, наладзіце getOrInsertComputed(key, callback), який запускае калебэк толькі у разы, калі ключ не знайдзены. Оба методы таксама існуюць у WeakMap; аспекты, прыменяюцыеся ў Node.js, практыкуецца у Node.js 26: Temporal, Map upserts і Undici 8.
Array.fromAsync() для обробкі асінхронных ітерабельных структураў
Сбор пагінаванага кліента API або чытальнага стрэму ў масэвую структуру раней значыў викорыстоўванне ручна напісанага цыклу for await...of, які дадаў элементы ў акумулятар. Array.fromAsync() спрацоўвае з асінхронным ітерабельным об’ектам, чакае на кожны элемент і прадаё звычную масэвую структуру.
// 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;
}
Неабяжны другі аргумент дазволяе перэкладзіць кожны элемент, пры чым таксама чакаеца на яго рэзультат, што падходзіць для асінхроннага варыянта функцыі map. Памятайце, што элементы обрабляюцца па спадчыннай зместо, по аднаму. Гэта падходзіць для стрэмоў і курсараў, але гэта не замена для Promise.all: якіму трэбае аднойчасна запусціць незалежныя прагнозы, Promise.all застаецца найкращым рашэнням. А буфераванне необмежанага стрэму ў памяці супершчытвае мету самага стрэмавання.
Памочныя функцыі для ітератараў заместо _.chain()
Самая сильная прычына для застаўкі Lodash — это _.chain(), які завдзяк ленівайеўцы ацэнке дазволяе методам map, filter і take-five пра 10 000 элементаў завершыцца як толькі будзе атрымана пяць рэзультаатаў. Методы масіва ўжо працуюць актываўна: .map() стварае цэлы проміжны масіў, .filter() зноў яго пераглядае, а .slice() пасля таго выкарыстоўвае большую частку роботы.
Памочныя прыемкі для ітэратараў, стандартызаваныя ў ES2025, робяць гэта ленівае працаванне натыўна. .values() вяртае ітэратар, а методы map, filter і take на яму выкарыстоўваюць по аднам элементу за раз, пакуль toArray() не скарыстаеся рэзультатамі.
// ❌ 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();
Кожны элемент працуе ў всім канале обробкі, перш чым запрашываецца наступны, таму heavyComputation выконваецца толькі пакуль не будзе знайдзена пяць падходжанняў. Недакладнасці: ітератары можна викорыстаць толькі аднакрат, няма функцый sort чы reverse, якія бы працавалі з адлегленым вычысленнем, а для маленькіх масэвых множын методы, якія выконваюцься немедленна, таксама шырокі і простейшыя у діагностыцы.
Галоўныя выводы
Math.sumPrecise()усувае накопічаныя памылкі заокруглення, але не можа выправіць неточныя даны; для валюты лепей викорыстаць цэлыя значэння.getOrInsert()заменяе функцыі has/set/get; для дорогіх значэнняў за замовчаннем лепей викорыстацьgetOrInsertComputed().Array.fromAsync()асэрыявана працуе з асінхроннымі ітерабельнымі об’ектамі; для паралелізма лепей викорыстацьPromise.all..values()у поўнай суворасці з інструментамі для ітератараў дае можлівасць створыць адлегленыя каналы обробкі, падобныя да_.chain(), без дапамогі залежнасцей.