[Javascript] defining functions before they're called
And Clover
and-babble at doxdesk.com
Mon Aug 24 18:49:51 CDT 2009
Paul Novitski wrote:
> where's the rationale for the declare-before-you-call scripting style?
> I think it has nothing to do with JavaScript functionality and has arisen
> because function source order matters [...] other programming languages
Well, yes... but it also makes a kind of sense. Program execution order
is top-to-bottom in JavaScript, so in you would not expect to be able to
refer to something you haven't defined yet.
Some static progamming languages allow forward-declaration by treating
functions as a completely different namespace, not interacting with the
run-time (variable) namespace at all. But that's not how JavaScript does
it; JS functions are first-class objects, whose references are stored in
perfectly normal variables.
The trick is: in JavaScript, the 'function' statement is magic.
When a block* is entered, the first thing it does is parse all the
syntax in the block. Then it looks for 'function' statements and lets
those run to define their functions first, before executing the rest of
the block. So if you write:
var x= alert;
function x(s) {
alert('hello');
};
x('bye');
the JS interpreter internally re-orders that into:
var x;
function x(s) {
alert('hello');
};
x= alert;
x('bye');
and hence you get 'bye', not 'hello' as you might have expected. The
ECMAScript-262 standard explains this in section 10.1.3. Well I say
'explains', but this is ECMAScript we're talking about, a document that
makes absolutely no concessions to clarity.
This only applies to the function statement, and not the function
expression! So if you changed the first example in a seemingly trivial way:
var x= alert;
x= function x(s) {
alert('hello');
};
x('bye');
you now have 'hello' instead of 'bye'!
*: what's a block, in this context? Well, a script file, a script
element, an inline event handler, a function body, a condition or
loop... for example this:
var x= alert;
if (true) {
function x(s) {
alert('hello');
};
}
x('bye');
keeps the definition of the function inside the 'if' instead of
reordering it out before the 'alert' assignment. So you get 'hello'.
For a dynamic scripting language this is all really incredibly spooky
and confusing; I can't think of another language that does anything like
this. It's another in the long-running series of JavaScript Strangenesses.
So, back to the question. Should you rely on forward-declaration in
JavaScript? Well... if you are reassigning and passing around
functions/methods as objects, then probably you shouldn't because the
order-of-execution is then not what it looks like and you'll get weird
errors.
If you are treating them purely as classic static functions, you can
probably get away with it. But even in this case you have to be careful
to keep them in the same block; put an if round them, or split the
script element into two, and they'll suddenly stop working.
All in all I would probably avoid it. In any case, it's very rarely
actually useful
--
And Clover
mailto:and at doxdesk.com
http://www.doxdesk.com/
More information about the Javascript
mailing list