I am getting a very strange output on the below scenarios:
function test(){
   var test=123;
   console.log(test)
}
// this output : 123
(function test(){
   var test=123;
   console.log(test)
})()
// this output: 123 
But when using the below code
(function test(){
   test=123;
   console.log(test)
})()
//output:
function test(){
    test=123;
    console.log(test)
}
Can anybody please explain.
What you're seeing isn't related to hoisting.
Your first example is quite straightforward:
(function test(){
   var test=123;
   console.log(test)
})()
You're creating a variable (via var) called test within the scope of the function, and assigning it a value, then outputting that value.
Your second example leaves out var:
(function test() {
    test = 123;
    console.log(test);
})();
...and so test has quite a different meaning: Within a function created by a named function expression, the function's name is an identifier resolving to the function. So test in that code is an identifier for the function.
That identifier is read-only when you've used a function expression, so your test = 123; line is ignored, and the console.log line outputs a representation of the function (as though test = 123; weren't there at all).
I'd forgotten that identifier is read-only (when created by an expression), but it is: From the specification:
FunctionExpression : functionBindingIdentifier ( FormalParameters ) {FunctionBody}
- If the function code for FunctionExpression is strict mode code, let strict be true. Otherwise let strict be false.
 - Let scope be the running execution context's LexicalEnvironment.
 - Let funcEnv be NewDeclarativeEnvironment(scope).
 - Let envRec be funcEnv's EnvironmentRecord.
 - Let name be StringValue of BindingIdentifier.
 - Perform envRec.CreateImmutableBinding(name, false).
 - ...
 
Note Step 6: The binding creating the identifier is immutable (can't be changed).
Note that this isn't true for the identifier (binding) created by a function declaration, which is mutable; but function expressions and function declarations treat the identifiers created by the function name completely differently. (For instance: A function declaration puts the name in scope where the declaration is, but a function expression doesn't.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With