Легитимные способы использования JavaScript 'with': примеры

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Оператор with в JavaScript способен обеспечить простоту доступа к свойствам объекта, однако это обычно происходит за счет снижения читаемости кода. В целях повышения ясности и качества кода рекомендуется избегать его применения, так как данный оператор может вызвать путаницу в областях видимости. В современном JavaScript большое предпочтение отдается деструктуризации объектов, что гарантирует его прозрачность и удобство чтения:

JS
Скопировать код
// Вместо 'with' мы выбираем современный подход – деструктуризацию.
let { make, model, year } = car;
console.log(`Едем на ${make} ${model} ${year} года выпуска`);
// Теперь понятно, откуда пришли переменные make, model и year.

Деструктуризация объектов является предпочтительным методом, обеспечивающим лаконичность без потери в читаемости и надежности кода.

Кинга Идем в IT: пошаговый план для смены профессии

Применение оператора "with" в целях упрощения кода

Оператор with предлагает иллюзию простоты, уменьшаю количество кода при обращении к свойствам объекта. Его полезность находят некоторые при работе с DOM:

JS
Скопировать код
// Хотя данный подход может быть заманчив для манипуляций с DOM, лучше его избегать.
with(document.forms[0].elements) {
  userName.style.backgroundColor = '#fafafa';
  password.style.backgroundColor = '#fafafa';
}

Такая запись синтаксиса может быть введена в заблуждение, усложняя отслеживание источника переменных и сделав код более сложным для поддержки.

Имитация блочной области видимости с помощью "with"

Перед появлением ES6 оператор with попросту использовался для симуляции блочной области видимости:

JS
Скопировать код
// Перед ES6 'with' использовали как костыль для создания блочного контекста, но есть и более совершенные способы.
with({x: 1}) {
  console.log(x); // Выведется: 1
}
// Анонимный объект создает временный контекст для x.

Не смотря на то, что использование with для симуляции блочных контекстов вполне рабочий способ, он может вызвать неясности при интерпретации кода, особенно в крупных проектах.

Использование оператора "with" при создании разметки

В некоторых специфических ситуациях, например, при создании разметки, можно использовать оператор with:

JS
Скопировать код
// Использование 'with' для сокращения записей при генерации SVG элементов – не самый удачный выбор.
with(document.createElementNS(svgNS, 'svg')) {
  setAttribute('width', 150);
  setAttribute('height', 150);
  // Здесь следуют дополнительные операции с атрибутами элемента SVG.
}

Такой подход может упростить вызовы API, но с другой стороны это может увеличить сложность понимания кода и вызвать проблемы с оптимизацией.

Забота о читаемости кода при использовании "with"

На первый взгляд оператор with может видеться полезным для автоматизации генерации шаблонов:

JS
Скопировать код
// При быстром просмотре оператор 'with' может показаться удобным в генерации шаблонов, но лучше его избегать.
with(templateContext) {
    output = `<h1>${title}</h1><p>${content}</p>`;
}

Но такой подход способен открыть «ящик Пандоры» возможных ошибок и запутанных областей видимости, что вероятно усложнит поддержку кода.

Почему современный JavaScript редко использует "with"

В современном JavaScript, особенно в условиях строгого режима, такие операторы, как with, обычно не рекомендуются, а то и вовсе запрещаются, по следующим причинам:

  • Скрытые ошибки: Опечатки или необъявленные переменные внутри блока with могут быть интерпретированы как свойства объекта, что усложняет отладку.
  • Когнитивная нагрузка: Сложность понимания происхождения переменных увеличивается, так как они могут быть как частью объекта with, так и глобальными.

Лучшие альтернативы "with"

Как совершенствующийся и усовершенствовавшийся разработчик, рассмотрите следующие альтернативы для более прозрачного управления контекстами:

  • Деструктуризация объектов: Экстракция нескольких свойств объекта одним действием, явно и без двусмысленности.
  • Краткая запись свойств: Использование { x } вместо { x: x } для лучшей читаемости и ясности.
  • Шаблонные строки (template literals): Используйте их для вставки переменных в строки, прощайте заковыристое конкатенирование.

Визуализация

Представим, что вы – художник, у которого есть палитра с разноцветными красками:

JS
Скопировать код
let palette = {red: "#ff0000", blue: "#0000ff", yellow: "#ffff00"};

Без оператора with вам приходится каждый раз обращаться к палитре:

JS
Скопировать код
canvas.paint(palette.red);
canvas.paint(palette.blue);

С использованием оператора with все цвета создают ощущение, будто они у вас под рукой:

JS
Скопировать код
with(palette) {
  canvas.paint(red);
  canvas.paint(blue);
}
Markdown
Скопировать код
Без 'with': 🎨↔↔↔🎨↔↔↔🎨
С 'with': 🎨✨ (Все цвета находятся в ваших руках! Заманчиво, правда?)

Примечание: Однако стоит помнить, что with лучше не использовать из-за возможной путаницы и ухудшения производительности. Это как бы палитра, которая хаотично смешивает краски и вызывает головокружение 🎨🌀.

Полезные материалы

  1. with – JavaScript | MDN — подробное описание оператора with.
  2. Что может дать использование оператора "with" в JavaScript? – Stack Overflow — общая дискуссия об использовании, шаблонах применения и потенциальных проблемах с производительностью на Stack Overflow.
  3. Спецификация языка ECMAScript – ECMA-262 Издание 5.1 — полное описание оператора with в официальной спецификации ECMAScript.
  4. Переменные и ограничение областей видимости в ECMAScript 6 — подробная статья о контекстах в ES6.
  5. Деструктуризация и обработка параметров в ECMAScript 6 — использование деструктуризации вместо оператора with.
  6. Ясное понимание "this" в JavaScript — JavaScript Is Sexy — статья о глубоком понимании контекста this в JavaScript.
  7. GitHub – airbnb/javascript: JavaScript Code Style — руководство по JavaScript код стилю от Airbnb рекомендует избегать with.