Contra: The with
statement makes it hard for a human reader or JavaScript compiler to decide whether an unqualified name will be found along the scope chain, and if so, in which object. So given this example:
function f(x, o) {
with (o) {
console.log(x);
}
}
Only when f
is called is x
either found or not, and if found, either in o
or (if no such property exists) in f
's activation object, where x
names the first formal argument. If you forget to define x
in the object you pass as the second argument, or if there's some similar bug or confusion, you won't get an error -- just unexpected results.
Contra: Code using with
may not be forward compatible, especially when used with something other than a plain object. Consider this example:
function f(foo, values) {
with (foo) {
console.log(values);
}
}
If you call f([1,2,3], obj)
in an ECMAScript 5 environment, then the values
reference inside the with
statement will resolve to obj
. However, ECMAScript 2015 introduces a values
property on Array.prototype
(so that it will be available on every array). So, in a JavaScript environment that supports ECMAScript 2015, the values
reference inside the with
statement could resolve to [1,2,3].values
. However, in this particular example, Array.prototype
has been defined with values
in its Symbol.unscopables
object. If it were not, one can see how this would be a difficult issue to debug.