The Now Platform® Washington DC release is live. Watch now!

Help
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
SlightlyLoony
Tera Contributor

find_real_file.pngSometimes 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:

a outer: 1
a inner: 2
b inner: 0
a inner: 2
b inner: 1
a outer: 1
b outer: undefined
But what he actually got was this:

a outer: 1
a inner: 2
b inner: 0
a inner: 2
b inner: 1
a outer: 2
b outer: 2
What in Knuth's name is going on here? Those last two log lines are just wrong!

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