What you see is not connected with the rise.
Your first example is pretty simple:
(function test(){ var test=123; console.log(test) })()
You create a variable (via var ) called test within the scope of the function and assign a value to it, and then output that value.
In your second example var :
(function test() { test = 123; console.log(test); })();
... and therefore test has a completely different meaning: inside a function created by a named function expression, the function name is the identifier that resolves the function. Thus, test in this code is the identifier for the function.
This identifier is read-only when you use a function expression, so your line is test = 123; is ignored, and the console.log line displays a representation of the function (as if test = 123; there was none at all).
I forgot that the identifier is read-only (when creating an expression), but this is: From the specification :
FunctionExpression: functionBindingIdentifier (FormalParameters) {FunctionBody}
- If the functional code for FunctionExpression is strict mode code, let strict be true. Otherwise, let strict be false.
- Let scope be the executable execution context of LexicalEnvironment.
- Let funcEnv be NewDeclarativeEnvironment (scope).
- Let envRec be funcEnv EnvironmentRecord.
- Let the name be StringValue BindingIdentifier.
- Run envRec.CreateImmutableBinding (name, false).
- ...
Note. Step 6: The binding creating the identifier is immutable (cannot be changed).
Note that this is not true for an identifier (binding) created by a function declaration that is mutable; but function expressions and function declarations handle identifiers created by a function name in completely different ways. (For example: A function declaration puts the name in scope, but the function expression does not matter.)
source share