Construction "with"

Lecture




  1. Example
  2. Variable changes
  3. Why abandoned with ?
    1. Replacement with
  4. Total

The with construction allows the use of an arbitrary object for the scope.

In modern JavaScript, this construction was abandoned, in strict mode it does not work, but it can still be found in the old code.

Syntax:

with (obj) {
   ... код ...
}

Any reference to the variable inside with first looks for it among the properties of obj , and only then - outside of with .

Example

In the example below, the variable will not be taken from the global domain, but from obj :

1 var a = 5;
2
3 var obj = { a : 10 };
4
5 with (obj) {
6    alert(a); // 10, из obj
7 }

Let's try to get a variable that is not in obj :

1 var b = 1;
2
3 var obj = { a : 10 };
4
5 with (obj) {
6    alert(b); // 1, из window
7 }

Here, the interpreter first checks for the presence of obj.b , does not find it, and goes outside with .

Especially funny is the use of nested with :

01 var obj = {
02    weight: 10,
03    size: {
04      width: 5,
05      height: 7
06    }
07 };
08
09 with (obj) {
10    with (size) { // size будет взят из obj
11      alert( width*height / weight ); // width,height из size, weight из obj
12    }
13 }

Properties from different objects are used as ordinary variables ... Magic! The search order of variables in the selected code: size => obj => window

  Construction with

Variable changes

When using with , as in nested functions, the variable changes in the area where it was found.

For example:

1 var obj = { a : 10 }
2
3 with (obj) {
4    a = 20;
5 }
6 alert(obj.a); // 20, переменная была изменена в объекте

Why abandoned with ?

There are several reasons.

  1. In the modern standard, JavaScript abandoned with because the with construction is error-prone and opaque.

    Problems arise when a variable is assigned in with(obj) , which is intended to be in the properties of obj , but not there.

    For example:

    1 var obj = { weight: 10 };
    2
    3 with (obj) {
    4    weight = 20; // (1)
    5    size = 35; // (2)
    6 }
    7
    8 alert(obj.size);
    9 alert(window.size);

    In line (2) assigned a property that is missing in obj . As a result, the interpreter, not finding it, creates a new global variable window.size .

    Such errors are rare, but very difficult to debug, especially if the size has changed not in a window , but somewhere in an external LexicalEnvironment .

  2. Another reason - JavaScript compression algorithms do not like with . Javascript is compressed before displaying on server. There are many tools for this, such as Closure Compiler and UglifyJS. In short, they either compress the code with with errors, or leave it partially uncompressed.
  3. And finally, performance - complicating the search for a variable due to with entails additional overhead . Modern engines use many internal optimizations, some of which cannot be applied to code that has with .

    Here, for example, run this code in a modern browser. The performance of the fast function is significantly different slow with an empty (!) with . And the point here is with , because the presence of this design impedes optimization.

    01 var i = 0;
    02
    03 function fast() {
    04    i++;
    05 }
    06
    07 function slow() {
    08    with (i) {}
    09    i++;
    10 }
    11
    12
    13 var time = new Date();
    14 while (i < 1000000) fast();
    15 alert( new Date - time);
    16
    17 var time = new Date();
    18 i=0;
    19 while (i < 1000000) slow();
    20 alert( new Date - time);

Replacement with

Instead of with it is recommended to use a temporary variable, for example:

01 /* вместо
02 with(elem.style) {
03    top = '10px';
04    left = '20px';
05 }
06 */
07
08 var s = elem.style;
09
10 s.top = '10px' ;
11 s.left = '0' ;

This is not so elegant, but it removes an extra level of nesting and it is absolutely clear what will happen and where properties will be assigned to.

Total

  • The with(obj) { ... } construct uses obj as an additional scope. All variables accessed inside the block are first searched in obj .
  • The with design is deprecated and not recommended for a number of reasons. Avoid her.

Importance: 5

Which function will be called?

1 function f() { alert(1) }
2
3 var obj = {
4    f: function () { alert(2) }
5 };
6
7 with (obj) {
8    f();
9 }

Decision

The second ( 2 ), because when accessing any variable inside with - it is searched first of all in the object.

Accordingly, 2 will be displayed:

1 function f() { alert(1) }
2
3 var obj = {
4    f: function () { alert(2) }
5 };
6
7 with (obj) {
8    f();
9 }

[Open task in new window]

Importance: 5

What will this code output?

1 var a = 1;
2
3 var obj = { b: 2 };
4
5 with (obj) {
6    var b;
7    alert( a + b );
8 }

Decision

Displays 3 .

The with construction does not create scopes; only functions create it. Therefore, the var b declaration inside the construct also works as if it were outside it.

The code in the problem is equivalent to this:

1 var a = 1;
2 var b;
3
4 var obj = { b: 2 }
5
6 with (obj) {
7    alert( a + b );
created: 2014-10-07
updated: 2021-03-13
132503



Rating 9 of 10. count vote: 2
Are you satisfied?:



Comments


To leave a comment
If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

Scripting client side JavaScript, jqvery, BackBone

Terms: Scripting client side JavaScript, jqvery, BackBone