⚡ Современные и малоизвестные возможности 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 разработке