Neil
Neil

Reputation: 5178

Javascript hoisting process with immediately invoked functions: Why doesn't this declared function run before function expression?

Code:

var funcExpression = function(){
  alert("function expression");  
}();

(function declarFunc(){
  alert("declared func");  
})();

The result is the function Expression is run first resulting in the alert "function expression" and the declared function is run second "declared func".

I know that during the hoisting process, declared functions are hoisted up entirely within their container and loaded into memory. Function expressions, however are not hoisted: they stay in the same place and are not loaded into memory until runtime(though the variable that points to the function expression is hoisted up and set to Undefined. (Please correct me if I have this concept wrong)

Since, the declared function is hoisted up above the function expression assignment, I would expect thus that the declared function is executed first: resulting in the alert "declared func" and then the function expression is executed afterwards: resulting in the second alert of "function expression".

However: it doesn't do what I expect. Thus, it seems like it has something to do with the immediate invocations of both the functions. Maybe the immediate invocations stay in the same order? Maybe after the hoisting process the code really looks like this:

var funcExpression = Undefined;

(function declarFunc(){
  alert("declared func");  
})

funcExpression = function(){
  alert("function expression");  
}();

(); // this executes declarFunc.  Maybe declarFunc is hoisted up 
    // but the invoking part stays in the same place?

Upvotes: 2

Views: 487

Answers (1)

Neil
Neil

Reputation: 5178

Solution after feedback and additional research

The answer is that BOTH of those functions are function expressions:

Code:

var funcExpression = function(){
  alert("function expression");  
}();

(function declarFunc(){
  alert("declared func");  
})();

so declareFunc() looks like a declared function, but since it is wrapped in parenthesis like that, it transforms it into a named function expression. The parenthesis following immediately evokes this function expression.

I was having trouble showing what the code looks like after the hoisting process because (function declarFunc(){...})() transforms into a named function expression due to those wrapping parenthesis. What this means is that outside of this named functions scope, we have no way to call it.

Example: If after these functions I did declarFunc() it will return with the error: ReferenceError: Can't find variable: declarFunc.

If we did want to make it possible to run this function expression then we would want to assign the function expression to a variable:

var foo = function declarFunc(){
  alert("declared func");  
};

Note: If we look at the console we will see that console.log(foo()) will return undefined, but the actions of the function will still take place. Just know that if no return statement is specified, then it implicitly returns undefined.

And now we can call on that function as many times as we would like with foo().

Upvotes: 1

Related Questions