Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable hoisting inside IIFE (lazy parsing)

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.

like image 866
ankur kushwaha Avatar asked Mar 11 '17 18:03

ankur kushwaha


Video Answer


1 Answers

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}

  1. If the function code for FunctionExpression is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let scope be the running execution context's LexicalEnvironment.
  3. Let funcEnv be NewDeclarativeEnvironment(scope).
  4. Let envRec be funcEnv's EnvironmentRecord.
  5. Let name be StringValue of BindingIdentifier.
  6. Perform envRec.CreateImmutableBinding(name, false).
  7. ...

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.)

like image 66
T.J. Crowder Avatar answered Oct 29 '22 19:10

T.J. Crowder