⚡ Современные и малоизвестные возможности JavaScript, о которых стоит знать
JavaScript постоянно развивается, и с каждым обновлением появляются новые фичи, которые делают старые практики устаревшими и менее эффективными. Ниже приведён список как новых, так и старых, но неочевидных возможностей языка, которые пригодятся любому разработчику.
🔁 Итераторы и их вспомогательные методы
Если ты когда-либо делал цепочку преобразований массива вроде:
arr.slice(10, 20).filter(el => el < 10).map(el => el + 5);
…то ты, возможно, не задумывался, насколько это неэффективно. Каждое преобразование создаёт новый массив. Для больших массивов (>500K элементов) это может стать серьёзной проблемой.
С недавних пор в JavaScript появились итераторные помощники — методы, которые работают как map
, filter
и т.д., но не создают временные массивы, а возвращают новые итераторы.
Вот основные:
drop(n)
— пропускает n
элементов (аналог slice(n)
).
take(n)
— берёт максимум n
элементов с начала (аналог slice(0, n)
).
some(fn)
/ every(fn)
— аналоги одноимённых методов массива.
filter(fn)
/ find(fn)
/ map(fn)
/ flatMap(fn)
— всё как в массивах.
reduce(fn, initial)
— как reduce
массива, но для итераторов.
forEach(fn)
— вызывает функцию для каждого элемента.
toArray()
— преобразует итератор в массив.
Их можно использовать с помощью Iterator.from()
или, например, arr.values()
:
arr.values()
.drop(10)
.take(10)
.filter(el => el < 10)
.map(el => el + 5)
.toArray();
⚠️ Поддержка появилась недавно. Например, Safari начал поддерживать только с 31 марта 2025 года, так что пока лучше использовать с осторожностью.
📍 Метод at()
Метод Array.prototype.at()
— это удобный способ получить элемент по индексу. Самое классное — он поддерживает отрицательные индексы:
[10, 20, 30].at(-1); // 30
[10, 20, 30].at(-2); // 20
Прощай, arr[arr.length - 1]
.
🧩 Promise.withResolvers()
Раньше, чтобы получить resolve
и reject
вне Promise, писали так:
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
Теперь можно проще:
const { promise, resolve, reject } = Promise.withResolvers();
📝 Замена строк с колбэком
Методы replace
и replaceAll
могут принимать функцию, а не строку:
let counter = 0;
console.log("NUMBER, NUMBER, NUMBER".replaceAll("NUMBER", (match) => `${match}=${++counter}`));
// → NUMBER=1, NUMBER=2, NUMBER=3
Позволяет эффективно делать множественные замены за один проход.
🔄 Обмен значениями
Не надо больше писать:
const temp = a;
a = b;
b = temp;
Теперь можно элегантнее:
[a, b] = [b, a];
Красиво и просто.
📦 structuredClone()
Альтернатива JSON.parse(JSON.stringify(obj))
, но безопаснее и быстрее. Она:
- Поддерживает
NaN
,undefined
,bigint
, циклические ссылки. - Работает быстрее и не ломается на рекурсивных объектах.
const obj = {};
obj.self = obj;
const clone = structuredClone(obj);
console.log(clone.self === clone); // true
🔖 Tagged templates
Многие знают про шаблонные строки, но не про тегированные шаблоны, которые позволяют обрабатывать строки функцией.
Пример — экранирование HTML:
function escapeHtml(strings, ...values) {
const div = document.createElement("div");
return strings.reduce((acc, str, i) => {
div.textContent = values[i] ?? "";
return acc + str + div.innerHTML;
}, "");
}
console.log(escapeHtml`<br> ${'<script>'}`); // <br> <script>
Позволяет кастомизировать шаблонные строки.
🧠 WeakMap
/ WeakSet
Как Map
и Set
, но:
- ключи только объекты (не строки/числа)
- элементы могут быть автоматически удалены при потере ссылок (garbage collection)
Полезно, когда нужно связать данные с объектом без риска утечек памяти.
const map = new WeakMap();
{
const obj = {};
map.set(obj, "value");
} // obj больше недоступен → будет удалён вместе с entry из WeakMap
🔣 Операции над множествами
В JavaScript теперь есть булевые операции для Set
:
const a = new Set([1, 2, 3, 4]);
const b = new Set([3, 4, 5, 6]);
a.union(b); // union() — объединение. Set(6) {1, 2, 3, 4, 5, 6}
a.intersection(b); // intersection() — пересечение. Set(2) {3, 4}
a.difference(b); // difference() — разность. Set(2) {1, 2}
a.symmetricDifference(b); // symmetricDifference() — симметричная разность. Set(4) {1, 2, 5, 6}
a.isDisjointFrom(b); // isDisjointFrom() — проверка, что множества не пересекаются. false
a.isSubsetOf(b); // isSubsetOf() — подмножество. false
a.isSupersetOf(b); // isSupersetOf() — надмножество. false
Подписывайтесь на FrontEndDev чтобы получать больше новостей о web разработке