JavaScript keeps throwing up interesting new tidbits for me. One that kind of freaked me out the other day is when functions and variables are created in a given block of code.
My expectation was that in a block of code, a sequence of statements, the statements would be executed in order, one after another, just like in most imperative languages. So for example in Python I can do something like:
def foo(): pass print foo
and expect output such as:
<function foo at 0x100407b18>
However, I would not expect the same output if I wrote the code something like this:
print foo def foo(): pass
and in fact, I don’t. I get something close to:
NameError: name 'foo' is not defined
Now in JavaScript, by contrast, I can do something like:
function foo() { }
console.log(foo);
and the console will dutifully have foo () printed in the log.
However, and here comes the fun part, I can also do this:
console.log(foo);
function foo() { }
which blows my mind. I guess this really comes in handy when... nope, can’t think of any good reason why this is a useful feature. (I’m sure there must be a good reason, but damned if I can work it out. But this is only where the fun begins. Because the same thing works for variables!
Now usually in Javascript, if you have a function, and write code like:
function foo() {
x = 37;
}
foo();
console.log("x:", x);
You find out you’ve stuffed up, and accidently written to the global object because for some brain-dead reason when you assign to a variable that doesn’t exist in JavaScript it will merrily walk up the scope chain to the global object and plonk it in there. If you do something like:
function foo() {
var x;
x = 37;
}
foo();
console.log("x:", x);
x will be undefined, and the x =
37 line will update the function’s locally scoped variable, and
not mess with the global object. But now comes the part that screws with
your head. You can just as easily write this as:
function foo() {
x = 37;
var x;
}
foo();
console.log("x:", x);
and it will have exactly the same effect. Now it is fairly clear what is happening here; as a function is parsed any variables and functions are created at that time. It turns out though that although variables are created, they are not initialised, so code such as:
var x = 12;
function foo() {
console.log("x:", x);
var x = 37;
}
foo();
will output x as undefined, (not 37, or 12). Now this
behaviour isn’t wrong, or necessarily bad, but it was certainly counter
to my expectation and experience in other languages.