The with
operator allows to use an arbitrary object as the scope.
It is used in the code around, but deprecated in modern JavaScript.
The syntax is:
with(obj) { ... }
When the interpreter meets a variable in the with
block, the lookup is made among the properties of obj
first, and then out of it.
Lookup example
The example below demonstrates how with
gets a value from the object.
var a = 5 var obj = { a : 10 } *!* with(obj) { alert(a) // 10 } */!*
Let’s try to access a variable not in obj
:
var a = 5, b = 1 var obj = { a : 10 } *!* with(obj) { alert(b) // 1 } */!*
The interpreter checks obj
for property b
, fails and takes it from outside of with
.
Nested with
are also possible:
var box = { weight: 10, size: { width: 5, height: 7 } } with(box) { with(size) { // size is taken from box *!* alert( width*height / weight ) // width,height from size, weight from box */!* } }
Note how properties from different levels of the object are used in one line. Magic
The variable lookup order is size => box => window
:
Setting example
When the variable is found in the object, it can be changed:
var a = 5 var obj = { a : 10 } *!* with(obj) { a = 20 } */!* alert(obj.a)
Another one from the real life:
with(elem.style) { position = 'absolute' left = '10px' top = '0' }
In the example above, elem.style.position
, elem.style.left
and elem.style.top
receive new values.
Why with
is deprecated?
People don’t like with
, because it gives the illusion of working with the object.
Unfortunately, that’s just an illusion. It is possible to lookup a variable, to change it, but if you try to add it.. Whops! Failure!..
In the example below, we take the box
and try to modify it’s properties. Everything is fine, until we try to add a new one in the line :
var box = { weight: 10 } with(box) { weight = 20 size = 35 // (*) } alert(box.size) alert(window.size)
There is no size
property in the box
. So the lookup process doesn’t stop at with
, it goes up. In this example, there is no size
at all, so the interpreter creates a new window.size
variable.
That’s possibly not the result we want. Such bugs are rare, but very hard to debug.
Another reason for not recommending with
is JavaScript compression algorithms which can’t handle with
reliably.
And finally, the intermediate scope introduced by with
slows down the execution. Modern JavaScript interpreters want to be extremely fast, as close to native code as possible. So, removing with
removes one of performance problems.
Instead of with
, it is recommended to use a temporary variable:
var s = elem.style s.position = 'absolute' s.top = '10px' s.left = '0'
That’s not so elegant, but evades additional nesting level and is more bug-proof.
Summary
- The
with(obj) { ... }
operator treatsobj
as an extra scope. All variables inside the block are first searched in the properties ofobj
, and then in the outside scope. - The
with
operator is deprecated and not recommended for a number of reasons. Try to evade it. - JavaScript compressors are buggy when you use
with
.