SlightlyLoony
Tera Contributor
Options
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
09-29-2011
04:28 AM
Sometimes the most innocent-looking code can really bend your mind — especially if it violates some deeply held notion you have about how things actually work inside a computer. That's exactly what's happened to the formerly normal fellow at right after running this unexpectedly diabolical snippet of code:
test();
function test() {
var a = 1;
gs.log('a outer: ' + a);
for (var b = 0; b < 2; b++) {
var a = 2;
gs.log('a inner: ' + a);
gs.log('b inner: ' + b);
}
gs.log('a outer: ' + a);
gs.log('b outer: ' + b);
}
It did not log what he expected!
He was expecting this:
But what he actually got was this:
a outer: 1
a inner: 2
b inner: 0
a inner: 2
b inner: 1
a outer: 1
b outer: undefined
What in Knuth's name is going on here? Those last two log lines are just wrong!
a outer: 1
a inner: 2
b inner: 0
a inner: 2
b inner: 1
a outer: 2
b outer: 2
Well, they're not really wrong, of course. But if you're used to the 'C' family of languages (C, C++, C#, Java, etc.), they surely look wrong. Two features of JavaScript are combining here to produce the unexpected result.
The first is that JavaScript (unlike the 'C' family of languages) doesn't have variable scopes inside code blocks defined by curly braces (these are sometimes called compound statements). In other words, in JavaScript variables defined inside a code block are accessible outside that code block. Like the other langauges, JavaScript does have variable scopes inside functions or methods (so variables defined inside a function are not accessible outside that function), plus there's a separate global scope which some other 'C' family languages have as well. But the absence of variable scopes inside code blocks sets JavaScript apart. This JavaScript feature is why the last line of the log is different than you might expect: in JavaScript, the variable b is accessible outside the code block it was defined in.
The second is that JavaScript (again, unlike the 'C' family of languages) lets you redeclare variables anytime you'd like. Any redeclarations that include initializers act like assignments. The following code is perfectly legal in JavaScript (you end up with a single variable a with a value of 2), but would get you in trouble in any other 'C' family language:
var a = 1;
var a = 2;
Now that's a silly example, but consider the function we started out with. In it, the variable a is declared at the beginning of the function, and again inside the loop's code block. Remember that there is no separate variable scope inside code blocks — so that second declaration of a is redeclaring the original variable. That's why the next-to-last log line had the unexpected 2 — the second declaration assigned a 2 to the originally declared variable a.
Some people are quite irritated by these JavaScript features. On the forums and message boards that discuss programming languages, it's easy to find discussion threads on this topic filled with fanatically defended views (for and against), vitriol, and disgusting suggestions. The fellow above had normal hair and no perforations before engaging in these discussions. I don't recommend getting excited about such things myself. After all, what matters to getting your job done isn't the righteousness of a language feature. What matters is whether you know how to use it...
1 Comment
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.