JavaScript Hoisting Explained |
Written by Mike James | ||||||
Wednesday, 23 January 2013 | ||||||
Page 2 of 2
Recap
This is the basic idea and it is very simple but there are some subtle points we need to consider. Implicit Variable DeclarationsJavaScript doesn't insist that you actually write the var to declare a variable - it might be simpler if it did and in later versions with strict turned on it does. It is enough to assign a value to a variable to declare it. That is if you write
and this is the first time myVariable has appeared then the variable is declared and set to 10. However the implicit declaration of the variable is not hoisted. If you think of
as equivalent to
then you might be surprised that the declaration isn't hoisted. The trick, is of course, that implicit declaration isn't equivalent to explicit declaration. If you write
then myVariable is created as a global variable - even if the instruction is within a function - whereas:
always creates a variable in the current scope be it global or local to a function. So to be hoisted a variable declaration has to be explicit and make use of the var keyword. If you don't use the var keyword then the variable is global and isn't hoisted even in the main program. InitializationAs well as declaring a variable you can also initialize it in the same instruction. For example:
both declares myVariable and initializes it to 10. By the hoisting rules this declaration should be treated as if it was at the start of the current scope - and it is. The complication is that the initialization is left exactly where it is - you can't alter the order of executable instructions in a program. That is
is treated as a shorthand for
and the declaration var myVariable is moved to the top of the current scope but the initialization is left where it is. This is good news because without this rule things could become very complicated very quickly. For example what about:
Moving the entire instruction to the top of the scope could alter the result returned by myFunction - imagine it is a timer say. Assignment is a runtime operation and needs to be executed exactly where the programmer wrote it. So the rules for variable declarations are:
Anonymous functionsNow we reach the promised complication in defining functions that stops forward referencing work. As well as named functions you can also create anonymous functions which can either be executed at once or assigned to a variable. Now you should be ahead of me at the mention of an assignment. As an assignment is an executable statement it shouldn't be moved and hence it shouldn't be hoisted - and there is no sensible way the function declaration can be hoisted without moving the assignment as well. That is: anonymous functions should not be hoisted. Consider the following example:
You really should be expecting what happens in this case. The variable declaration myFunction is hoisted so when we try to call myFuncton the variable is declared but its value is undefined because the assignment isn't hoisted. If you include an alert(myFunction) at the start of the program you will see that it is indeed undefined So now you can see why:
works perfectly, the forward reference is allowed courtesy of hoisting, but
doesn't work because without hoisting you can't forward reference the function. This is the reason why you can use a named function before it is defined but an anonymous function has to be defined before it can be used. An anonymous function is treated differently by JavaScript - it is more a function expression than a function declaration. Overriding VariablesYou can see why the hoisting of function declaration is important - it allows forward referencing. The real question is why bother hoisting variable declarations. After all forward referencing variable is not a problem in JavaScript because using a variable implicitly creates it i.e. implicitly declares it. The important point is that an implicit declaration creates a global variable but an explicit declaration creates a variable in the current scope - and this makes a big difference. For example if you create a local variable with the same name as a global variable then it hides the global in the local scope. For example
This works as you would expect and the alert displays 10 as the value of the global variable myGlobal. Now make a small change to the program to get:
This declares a local variable within the function which has the same name as the global. If you don't know about hoisting then you probably expect the program two display 10 as before. However the declaration is hoisted and hence myGlobal, the local variable, exists from the start of the function and hides the global variable. The value in the local variable is undefined and so this is what the alert displays. Hoisting converts the program into:
The rule is that explicit variable declarations behave as if they are at the top of the current scope and therefore hide any variables in the containing scopes right from the start of the current scope. Best PracticeHoisting was introduced to allow you to forward reference functions and variables. However, the best advice for avoiding difficulties with hoisting is to actually do the job manually. Always declare variables at the start of the main program or function - initializing if necessary and where necessary. As to functions? If you are using function declarations then define them in an order that is logical for the understanding of the program. If you are using anonymous functions then you have to take account of where they are used and where they are defined - there seems to be no way of simplifying this and you just have to take into account that you can't forward reference an anonymous function.
If you have any thoughts on how to organize declarations in JavaScript use the comments to contribute.
Related ArticlesThe Undefined Defined Variable
To be informed about new articles on I Programmer, subscribe to the RSS feed, follow us on Google+, Twitter, Linkedin or Facebook, install the I Programmer Toolbar or sign up for our weekly newsletter.
Comments
or email your comment to: comments@i-programmer.info
|
||||||
Last Updated ( Wednesday, 23 January 2013 ) |