Эта статья объясняет как работает with в JavaScript и почему его не рекомендуется использовать.
with создает новую область видимости «scope» и представляет свойства объекта «object» как локальные переменные выражения «statement». Пример (скобки не обязательны для одного выражения, но их рекомендуется использовать):
Существует похожий объект свойства которого одновременно являются глобальными переменными — этот объект называется global (в браузерах это window). Но в отличии от глобального объекта, переменные, которые объявлены в выражении with (блок statement) не добавляются к объекту «object», а просачиваются во внешний scope и существуют дальше.
Использование выражения with не желательно. Его использование запрещено в Strict Mode:
Чем же заменить with:
Вместо передачи переменной в with используйте короткое имя:
Если вы не желаете объявлять временную переменную в вашем scope, то используйте IIFE:
Вы также можете переслать этот объект в качестве параметра IIFE:
Чтобы понять почему with является устаревшим, давайте рассмотрим пример и увидим как аргумент функции меняет её поведение. Вот эта функция:
Запустим функцию с разными параметрами:
Есть две причины по которым with является устаревшим:
Производительность: оператор with невозможно оптимизировать автоматически, потому что заранее не известно куда будет ссылаться arg: на реальную переменную или на свойство переменной внутри with. Это может измениться при каждом вызове.
Безопасность: нельзя определить куда ссылается переменная глядя на её окрестности (её лексическое окружение). По словам Brendan Eich именно из-за этого with считается устаревшим, а не из-за соображений производительности.
Синтаксис оператора with
with (object)
statement
with создает новую область видимости «scope» и представляет свойства объекта «object» как локальные переменные выражения «statement». Пример (скобки не обязательны для одного выражения, но их рекомендуется использовать):
with({ first: "John" }) { console.log("Hello " + first); } // Hello John
Существует похожий объект свойства которого одновременно являются глобальными переменными — этот объект называется global (в браузерах это window). Но в отличии от глобального объекта, переменные, которые объявлены в выражении with (блок statement) не добавляются к объекту «object», а просачиваются во внешний scope и существуют дальше.
with({}) { var x = "abc"; }
console.log(x) // 'abc'
Оператор with является устаревшим
Использование выражения with не желательно. Его использование запрещено в Strict Mode:
function foo() { "use strict"; with({}); }
// SyntaxError: strict mode code may not contain 'with' statements
Чем же заменить with:
with(foo.bar.baz) {
console.log("Hello "+first+" "+last);
}
Вместо передачи переменной в with используйте короткое имя:
var b = foo.bar.baz;
console.log("Hello "+b.first+" "+b.last);
Если вы не желаете объявлять временную переменную в вашем scope, то используйте IIFE:
(function() {
var b = foo.bar.baz;
console.log("Hello "+b.first+" "+b.last);
}());
Вы также можете переслать этот объект в качестве параметра IIFE:
(function(b) {
console.log("Hello "+b.first+" "+b.last);
}(foo.bar.baz));
Так почему же with — это плохо
Чтобы понять почему with является устаревшим, давайте рассмотрим пример и увидим как аргумент функции меняет её поведение. Вот эта функция:
function foo(arg) {
with(arg) {
console.log("arg: " + arg)
}
}
Запустим функцию с разными параметрами:
foo("Hello");
// arg: Hello - параметр arg
foo({});
// arg: [object Object] - параметр arg
foo({ arg: "Hello" });
// arg: Hello - свойство arg.arg!
Есть две причины по которым with является устаревшим:
Производительность: оператор with невозможно оптимизировать автоматически, потому что заранее не известно куда будет ссылаться arg: на реальную переменную или на свойство переменной внутри with. Это может измениться при каждом вызове.
Безопасность: нельзя определить куда ссылается переменная глядя на её окрестности (её лексическое окружение). По словам Brendan Eich именно из-за этого with считается устаревшим, а не из-за соображений производительности.