The "with" operator

  1. Lookup example
  2. Setting example
  3. Why with is deprecated?
  4. Summary

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 Smile

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 Star:

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 treats obj as an extra scope. All variables inside the block are first searched in the properties of obj, 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.

Tutorial

Donate

Donate to this project