The reason is in the way ECMAScript code is processed.
During initialisation, function declarations are processed first, then variable declarations (a process often called "hoisting"). Then execution begins.
Function expressions are evaluated during execution.
So you can't execute function declarations immediately because even variables don't exist yet and other code that the function might depend on hasn't been executed either.
Consider something as simple as:
foo(); // shows undefined
var randomNumber = function() { // function expression
return Math.random();
}(); // () makes it an IIFE
foo(); // shows value assigned to randomNumber
function foo() { // function declaration
alert(randomNumber);
}
Function foo exists before randomNumber (despite the sequence of the code), so attempting to execute it immediately would throw a reference error. Once initialisation is complete, both foo and randomNumber have been declared.
The code on the RHS of the assignment to randomNumber is parsed during initialisation for syntax errors, but not executed until the execution phase.
Now execution begins, the function expression is executed and assigns a value to randomNumber so when foo is called, randomNumber exists and has whatever value the function expression on the RHS returned.