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
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.
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.
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.
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.
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.
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 ;)