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

后端 未结 30 1663
伪装坚强ぢ
伪装坚强ぢ 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:28

    I think the obvious use is as a shortcut. If you're e.g. initializing an object you simply save typing a lot of "ObjectName." Kind of like lisp's "with-slots" which lets you write

    (with-slots (foo bar) objectname
       "some code that accesses foo and bar"
    

    which is the same as writing

    "some code that accesses (slot-value objectname 'foo) and (slot-value objectname 'bar)""
    

    It's more obvious why this is a shortcut then when your language allows "Objectname.foo" but still.

    0 讨论(0)
  • 2020-11-22 05:28

    Using with also makes your code slower in many implementation, as everything now gets wrapped in an extra scope for lookup. There's no legitimate reason for using with in JavaScript.

    0 讨论(0)
  • 2020-11-22 05:29

    Visual Basic.NET has a similar With statement. One of the more common ways I use it is to quickly set a number of properties. Instead of:

    someObject.Foo = ''
    someObject.Bar = ''
    someObject.Baz = ''
    

    , I can write:

    With someObject
        .Foo = ''
        .Bar = ''
        .Baz = ''
    End With
    

    This isn't just a matter of laziness. It also makes for much more readable code. And unlike JavaScript, it does not suffer from ambiguity, as you have to prefix everything affected by the statement with a . (dot). So, the following two are clearly distinct:

    With someObject
        .Foo = ''
    End With
    

    vs.

    With someObject
        Foo = ''
    End With
    

    The former is someObject.Foo; the latter is Foo in the scope outside someObject.

    I find that JavaScript's lack of distinction makes it far less useful than Visual Basic's variant, as the risk of ambiguity is too high. Other than that, with is still a powerful idea that can make for better readability.

    0 讨论(0)
  • 2020-11-22 05:29

    Using "with" can make your code more dry.

    Consider the following code:

    var photo = document.getElementById('photo');
    photo.style.position = 'absolute';
    photo.style.left = '10px';
    photo.style.top = '10px';
    

    You can dry it to the following:

    with(document.getElementById('photo').style) {
      position = 'absolute';
      left = '10px';
      top = '10px';
    }
    

    I guess it depends whether you have a preference for legibility or expressiveness.

    The first example is more legible and probably recommended for most code. But most code is pretty tame anyway. The second one is a bit more obscure but uses the expressive nature of the language to cut down on code size and superfluous variables.

    I imagine people who like Java or C# would choose the first way (object.member) and those who prefer Ruby or Python would choose the latter.

    0 讨论(0)
  • 2020-11-22 05:29

    I think the object literal use is interesting, like a drop-in replacement for using a closure

    for(var i = nodes.length; i--;)
    {
           // info is namespaced in a closure the click handler can access!
           (function(info)
           {           
                nodes[i].onclick = function(){ showStuff(info) };
           })(data[i]);
    }
    

    or the with statement equivilent of a closure

    for(var i = nodes.length; i--;)
    {
           // info is namespaced in a closure the click handler can access!
           with({info: data[i]})
           {           
                nodes[i].onclick = function(){ showStuff(info) };
           }        
    }
    

    I think the real risk is accidently minipulating variables that are not part of the with statement, which is why I like the object literal being passed into with, you can see exactly what it will be in the added context in the code.

    0 讨论(0)
  • 2020-11-22 05:29

    My

    switch(e.type) {
        case gapi.drive.realtime.ErrorType.TOKEN_REFRESH_REQUIRED: blah
        case gapi.drive.realtime.ErrorType.CLIENT_ERROR: blah
        case gapi.drive.realtime.ErrorType.NOT_FOUND: blah
    }
    

    boils down to

    with(gapi.drive.realtime.ErrorType) {switch(e.type) {
        case TOKEN_REFRESH_REQUIRED: blah
        case CLIENT_ERROR: blah
        case NOT_FOUND: blah
    }}
    

    Can you trust so low-quality code? No, we see that it was made absolutely unreadable. This example undeniably proves that there is no need for with-statement, if I am taking readability right ;)

    0 讨论(0)
提交回复
热议问题