Are there legitimate uses for JavaScript's “with” statement?

后端 未结 30 2145
伪装坚强ぢ
伪装坚强ぢ 2020-11-22 04:22

Alan Storm\'s comments in response to my answer regarding the with statement got me thinking. I\'ve seldom found a reason to use this particular language feature, and had ne

30条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-11-22 05:03

    Another use occurred to me today, so I searched the web excitedly and found an existing mention of it: Defining Variables inside Block Scope.

    Background

    JavaScript, in spite of its superficial resemblance to C and C++, does not scope variables to the block they are defined in:

    var name = "Joe";
    if ( true )
    {
       var name = "Jack";
    }
    // name now contains "Jack"
    

    Declaring a closure in a loop is a common task where this can lead to errors:

    for (var i=0; i<3; ++i)
    {
       var num = i;
       setTimeout(function() { alert(num); }, 10);
    }
    

    Because the for loop does not introduce a new scope, the same num - with a value of 2 - will be shared by all three functions.

    A new scope: let and with

    With the introduction of the let statement in ES6, it becomes easy to introduce a new scope when necessary to avoid these problems:

    // variables introduced in this statement 
    // are scoped to each iteration of the loop
    for (let i=0; i<3; ++i)
    {
       setTimeout(function() { alert(i); }, 10);
    }
    

    Or even:

    for (var i=0; i<3; ++i)
    {
       // variables introduced in this statement 
       // are scoped to the block containing it.
       let num = i;
       setTimeout(function() { alert(num); }, 10);
    }
    

    Until ES6 is universally available, this use remains limited to the newest browsers and developers willing to use transpilers. However, we can easily simulate this behavior using with:

    for (var i=0; i<3; ++i)
    {
       // object members introduced in this statement 
       // are scoped to the block following it.
       with ({num: i})
       {
          setTimeout(function() { alert(num); }, 10);
       }
    }
    

    The loop now works as intended, creating three separate variables with values from 0 to 2. Note that variables declared within the block are not scoped to it, unlike the behavior of blocks in C++ (in C, variables must be declared at the start of a block, so in a way it is similar). This behavior is actually quite similar to a let block syntax introduced in earlier versions of Mozilla browsers, but not widely adopted elsewhere.

提交回复
热议问题