Что используешь из последних нововведений JS?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Актуальные нововведения JavaScript в моей практике
Современный JavaScript развивается стремительно, и я активно использую следующие нововведения из спецификаций ES2021-ES2023, которые значительно улучшают читаемость, безопасность и выразительность кода.
Оператор нулевого слияния с присваиванием (??=) и логическое И с присваиванием (&&=)
Эти операторы из ES2021 прекрасно заменяют громоздкие проверки на null/undefined:
// Старая запись
let config = { timeout: null };
if (config.timeout === null || config.timeout === undefined) {
config.timeout = 3000;
}
// Новая запись с ??=
config.timeout ??= 3000;
// Практический пример с кэшированием
let cachedData;
function getData() {
cachedData &&= await fetchData(); // Перезаписывает только если truthy
return cachedData ??= await fetchFreshData(); // Инициализирует если null/undefined
}
Методы replaceAll() и at() для строк и массивов
Метод replaceAll() решает классическую проблему глобальной замены в строках без регулярных выражений:
// Раньше нужно было использовать RegExp с флагом g
const text = "apple,banana,apple,orange";
const updated = text.replace(/apple/g, "pear");
// Теперь гораздо читабельнее
const updatedModern = text.replaceAll("apple", "pear");
Метод at() предоставляет удобный доступ к элементам с конца коллекции:
const array = [10, 20, 30, 40];
// Получение последнего элемента
const lastOld = array[array.length - 1]; // 40
const lastNew = array.at(-1); // 40 - намного элегантнее!
// Также работает со строками
const str = "Hello";
console.log(str.at(-1)); // "o"
Приватные поля и методы классов
Приватные поля (с префиксом #) из ES2022 наконец-то дали настоящую инкапсуляцию в JavaScript:
class UserSession {
// Приватное поле
#sessionToken = null;
// Приватный метод
#generateToken() {
return Math.random().toString(36).substring(2);
}
constructor() {
this.#sessionToken = this.#generateToken();
}
get token() {
return this.#sessionToken;
}
// Публичный метод, использующий приватный
refresh() {
this.#sessionToken = this.#generateToken();
return this.#sessionToken;
}
}
const session = new UserSession();
// session.#sessionToken // SyntaxError - недоступно извне
// session.#generateToken() // SyntaxError - недоступно извне
Статические поля и приватные статические методы
Статические блоки инициализации позволяют выполнять сложную логику при инициализации класса:
class Configuration {
static #apiKey;
static #config = {};
// Статический блок инициализации
static {
try {
this.#apiKey = process.env.API_KEY;
this.#config = this.#loadConfig();
} catch (error) {
this.#apiKey = 'default-key';
this.#config = { retries: 3 };
}
}
static #loadConfig() {
// Сложная логика загрузки конфигурации
return JSON.parse(localStorage.getItem('appConfig')) || {};
}
static get apiKey() {
return this.#apiKey;
}
}
Top-level await в модулях
Возможность использовать await на верхнем уровне модулей (ES2022) изменила подход к инициализации приложений:
// Раньше нужно было оборачивать в асинхронную функцию
(async () => {
const config = await fetchConfig();
const data = await initializeApp(config);
startApp(data);
})();
// Теперь можно напрямую в модуле
const config = await fetch('/api/config').then(r => r.json());
const user = await authenticateUser();
const app = await initializeApplication({ config, user });
// Особенно полезно для динамических импортов
const heavyModule = await import('./heavy-module.js');
Новые методы массивов: toSorted(), toReversed(), toSpliced(), with()
Методы из ES2023 обеспечивают иммутабельные операции над массивами, что критически важно для работы с React и другими фреймворками:
const original = [5, 2, 8, 1, 9];
// Иммутабельная сортировка
const sorted = original.toSorted((a, b) => a - b);
console.log(original); // [5, 2, 8, 1, 9] - не изменился!
console.log(sorted); // [1, 2, 5, 8, 9]
// Иммутабельное изменение элемента по индексу
const updated = original.with(2, 100);
console.log(updated); // [5, 2, 100, 1, 9]
// Иммутабельный reverse
const reversed = original.toReversed();
// Особенно полезно в React компонентах
function TodoList({ items }) {
const addItem = (newItem) => {
// toSpliced вместо push + spread оператора
setItems(prev => prev.toSpliced(prev.length, 0, newItem));
};
}
WeakRef и FinalizationRegistry
Для продвинутого управления памятью и кэширования:
class ExpensiveResource {
constructor(data) {
this.data = data;
}
}
class ResourceCache {
#cache = new Map();
#registry = new FinalizationRegistry(key => {
console.log(`Ресурс ${key} был собран сборщиком мусора`);
this.#cache.delete(key);
});
get(key) {
let weakRef = this.#cache.get(key);
if (weakRef) {
const resource = weakRef.deref();
if (resource) return resource;
}
const newResource = new ExpensiveResource(/* ... */);
weakRef = new WeakRef(newResource);
this.#registry.register(newResource, key);
this.#cache.set(key, weakRef);
return newResource;
}
}
Эти нововведения я активно применяю в production-проектах, так как они:
- Улучшают читаемость кода
- Повышают безопасность через настоящую инкапсуляцию
- Упрощают обработку ошибок
- Способствуют функциональному программированию через иммутабельные операции
- Оптимизируют производительность в современных браузерах
При этом я всегда учитываю поддержку браузеров и при необходимости настраиваю соответствующий транспилятор (Babel) и полифиллы для обеспечения обратной совместимости.