Конструкция with
позволяет использовать для области видимости произвольный объект.
В современном JavaScript от этой конструкции отказались, в строгом режиме она не работает, но ее еще можно найти в старом коде.
Синтаксис:
Любое обращение к переменной внутри with
сначала ищет ее среди свойств obj
, а только потом — вне with
.
Пример
В примере ниже переменная будет взята не из глобальной области, а из obj
:
Попробуем получить переменную, которой в obj
нет:
Здесь интерпретатор сначала проверяет наличие obj.b
, не находит и идет вне with
.
Особенно забавно выглядит применение вложенных with
:
Свойства из разных объектов используются как обычные переменные… Магия! Порядок поиска переменных в выделенном коде: size => obj => window
Изменения переменной
При использовании with
, как и во вложенных функциях — переменная изменяется в той области, где была найдена.
Например:
Почему отказались от with
?
Есть несколько причин.
- В современном стандарте
JavaScript
отказались от with
, потому что конструкция with
подвержена ошибкам и непрозрачна.
Проблемы возникают в том случае, когда в with(obj)
присваивается переменная, которая по замыслу должна быть в свойствах obj
, но ее там нет.
Например:
В строке (2)
присваивается свойство, отсутствующее в obj
. Об этом говорит сайт https://intellect.icu . В результате интерпретатор, не найдя его, создает новую глобальную переменную window.size
.
Такие ошибки редки, но очень сложны в отладке, особенно если size
изменилась не в window
, а где-нибудь во внешнем LexicalEnvironment
.
- Еще одна причина — алгоритмы сжатия JavaScript не любят
with
. Перед выкладкой на сервер JavaScript сжимают. Для этого есть много инструментов, например Closure Compiler и UglifyJS. Если вкратце — они либо сжимают код с with
с ошибками, либо оставляют его частично несжатым.
- Ну и, наконец, производительность — усложнение поиска переменной из-за
with
влечет дополнительные накладные расходы. Современные движки применяют много внутренних оптимизаций, ряд которых не могут быть применены к коду, в котором есть with
.
Вот, к примеру, запустите этот код в современном браузере. Производительность функции fast
существенно отличается slow
с пустым(!) with
. И дело тут именно в with
, т.к. наличие этой конструкции препятствует оптимизации.
Замена with
Вместо with
рекомендуется использовать временную переменную, например:
Это не так элегантно, но убирает лишний уровень вложенности и абсолютно точно понятно, что будет происходить и куда присвоятся свойства.
Итого
- Конструкция
with(obj) { ... }
использует obj
как дополнительную область видимости. Все переменные, к которым идет обращение внутри блока, сначала ищутся в obj
.
- Конструкция
with
устарела и не рекомендуется по ряду причин. Избегайте ее.
Важность: 5
Вторая (2
), т.к. при обращении к любой переменной внутри with
— она ищется прежде всего в объекте.
Соответственно, будет выведено 2
:
[Открыть задачу в новом окне]
Важность: 5
Выведет 3
.
Конструкция with
не создает области видимости, ее создают только функции. Поэтому объявление var b
внутри конструкции работает также, как если бы оно было вне ее.
Код в задаче эквивалентен такому:
Комментарии
Оставить комментарий
Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)
Термины: Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)