Thursday, December 27, 2012

"Hoisting" in JavaScript

I came across the term "Hoisting" whilst watching a tutorial and wanted to post an example on it. Everyone who works with JavaScript probably already knows that functions can be defined below where they are actually called.

For example:

log1();

function log1() {
   ...
};


The above is possible even though JavaScript is a top-down programming language, i.e. it executes code top to bottom at runtime. This ability is essentially what is known as "Hoisting" in JavaScript. So basically, the JavaScript compiler looks ahead and checks for a functions existance before it throws a "function not defined" error.

But there is a caveat to this...

As you may know, functions in JavaScript are objects and you can define them in many ways. The "basic" way is shown above in the log1 function, but you can also define this same function as follows:

var log2 = function() {
   ...
};

log2(); 


This is also a very common way to define a function but what's interesting is that if you declare your function like I have done in log2, your function is no longer "Hoisted" by the JavaScript compiler!

I have come across this issue many times whilst working with complex JavaScript code bases that are built heavily on object oriented concepts but never understood why I get I would only sometimes get the "function not defined" error. Turns out, this is the reason.

I'm not sure exactly why this is so, my guess would be that the compiler only looks for the "basic" function definitions to keep the runtime efficient, but if anyone knows the exact reason please comment below.

Happy Coding!


UPDATE - 3 July 2012

It's also important to note that variables in functions and the global scope and hoisted to the top as well. Have a look at this example:

function showName () {
    console.log ("First Name: " + name); // prints 'undefined'
    var name = "Ford";
    console.log ("Last Name: " + name); // prints 'Ford'
}

showName(); 

The reason we can call showName() without a JS error (cause it looks like in the first line of the function we are trying to print 'name' before it was initialised and this should cause a runtime error) is because the variable name is hoisted to the top of the showName function.

I also worked out why when we define a function like in log2() it does not get hoisted. I was reading today, that the JS engine only hoists variable declarations and function declarations to the top of the scope its in (i.e. a local function scope or global scope). But variable and function assignments are NOT hoisted, so when we do 'var log2 = function()' this is actually a function assignment and therefore its not hoisted and we get a JS runtime error.

No comments:

Post a Comment

Fork me on GitHub