← Назад к вопросам

Что используешь из последних нововведений JS?

1.3 Junior🔥 141 комментариев
#JavaScript Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Актуальные нововведения 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) и полифиллы для обеспечения обратной совместимости.