Execution order of functions and variables in JavaScript and ActionScript.

April 13, 2009
Greg Ferrell

Many newcomers to web development may not be used to how web implementations of JavaScript execute. Namely, in what order it executes. This can be the source of many errors that are difficult to pinpoint if you aren’t experienced with it. I think this also affects people who are very experienced with other programming languages and fosters a lot of undeserved hate towards ActionScript and JavaScript. (It’s important to note that not all implementations of JavaScript are the same, and that some may in fact defer from what is said below. This article concerns browser and Flash based ECMAScript.)

The thing to understand about JavaScript is that it isn’t compiled for the most part. (This is not exactly true for ActionScript because of the introduction of classes in ActionScript 2.0, however, the runtime script remains the same. You might argue that it compiles into a *.swf file, but in reality, that is the combination of everything that has to do with the Flash file. The ActionScript still remains live.) It’s good that it isn’t compiled though, because this allows for much more dynamic, expressive coding.

So, if it isn’t compiled, how does it work? Browser-based JavaScript code is all executed at first calling, nothing is compiled or cached in a scope until it is called (except AS2 & AS3 classes). It works this way because, with the exception of basic, immutable variable types: strings, booleans, numbers, and ‘undefined’, every variable in JavaScript is an object. This includes ‘null’ and functions (‘null’ is technically a basic variable, but is reported as an object in JavaScript). Since functions are objects, this means their value in memory is also like an object and names are only assigned by reference. Lets see how this works:

//bob first initialization
function bob()
{
    alert('bob');
}

//set jan to bob via reference
var jan = bob;

//set bob to another function
function bob()
{
    alert('newbob');
}

jan(); //alerts 'bob'
bob(); //alerts 'newbob'

This where things can be very confusing to people who are used to other languages where functions are just functions and can only be written once to a variable name at compile time. In order to understand better, let’s write the same code again with anonymous functions:

//bob first initialization
var bob = function()
{
    alert('bob');
};

//set jan to bob via reference
var jan = bob;

//set bob to another function
bob = function()
{
    alert('newbob');
};

jan(); //alerts 'bob'
bob(); //alerts 'newbob'

This is how functions are actually assigned in JavaScript. The traditional C style that was seen in the previous example is translated at runtime into something like the above. So, when you code JavaScript, imagine instead that all functions are really variable pointers to anonymous functions in memory. (ActionScript 3.0 in strict mode attempts to stop this sort of behavior by warning you when your code tries to overwrite variables that have already been set. While this is good for heavier languages, I think it is moving away from what makes ECMAScript really dynamic in the first place.)

At this point, you might be asking: “Why is all this important to the execution order of JavaScript?”. This gives you background as to why JavaScript doesn’t execute anything until runtime. In light of this, there is one thing JavaScript does to speed things up that is VERY important to understanding its execution order: JavaScript caches declared functions before any other variables, after this, it goes back to the top of the scope and runs variable definitions and functions calls in the order that they appear. This is where the confusion begins for the uninitiated.

Let’s say for example that you have a function that returns a value from a passed variable. You might want to assign a variable to the result of that function like so:

var newNumber = secondPower(5); //25

//first definition of function
function secondPower(n)
{
    return n * n;
}

This works because the function was cached before the variable was assigned. However, doing things this way in your own code is a TERRIBLE idea because it can cause more problems than it solves. Lets look at an example of where this might fail. Remember our previous example where we assigned the anonymous function to a variable name? While in that example, it worked perfectly, it actually causes a strange thing to happen to execution order:

var newNumber = secondPower(5); //error, secondPower is not defined yet

//some parsers would not even get this far due to the above error
//thrown errors in ECMAScript halt the execution scope they are in
var secondPower = function(n)
{
    return n * n;
};

var newNumber2 = secondPower(5); //25

This error happens because when the parser came through, it cached the anonymous function before anything else, but not the variable name assignment to the anonymous function. Therefore, when we called ‘secondPower’, it had not been assigned yet and the first calling was undefined and possibly threw an error. It is important to remember that the bad thing that happened here was not the fact that we assigned a variable name to an anonymous function in place of the classic C way to declare a function, but rather the bad idiom of calling a function before it is assigned. Anonymous functions offer huge benefits to ECMAScript and are not inherently bad.

Other problems can arise from calling functions before they are declared even if the function is written in the classic style. Perhaps the function we use for variable assignment requires an outside variable to function properly. This would cause an error if the function was called before the assignment of the dependent variable took place:

var newNumber = multiplyNumber(5);
//multiple is not defined yet, incorrect result with possible error 

var multiple = 2;

//this is cached and available before all other variables
function multiplyNumber(n)
{
    return n * multiple;
}

As we can see here, an error would occur in our variable assignment because even though the function was properly cached, its dependent was not assigned yet and the function could not execute properly.

So, knowing this, what should you do to avoid these errors? Here is a quick list to help you when writing your code:

  • Never call a function before it is declared
  • Declare all variables in a execution scope as soon as possible
  • Only assign variables to a function result after all functions and other variables have been declared

Just to reiterate, let’s look at how a good code setup should be writen:

//declare all variables as soon as possible
var newNumber, multiple = 2;

//declare all functions before calling them
function multiplyNumber(n)
{
    return n * multiple;
}

//finally, set variable values that require function results
newNumber = multiplyNumber(5); //10

Declaring your variables and functions in this way will allow you to use more expressive methods to set functions and will most importantly avoid errors. For some further reading, check out Douglas Crockford’s recommendations on JavaScript coding conventions.

While I mostly mentioned JavaScript in this Article, the majority of these principles and Douglas Crockford’s suggestions apply to ActionScript as well.