Why does the console log function a in an IIFE?

Viewed 252

var a = 1; 
(function a () { 
    a = 2;
    console.log("a:", a); 
})();

So apparently a as an IIFE (immediately invoked function expression) the function name will override the global variable a, which is understandable but...why isn't a reassigned to number 2 within the function itself?

function a() { 
    a = 1;
    console.log("a:", a); 
};
function a() { 
    a = 2;
    console.log("a:", a); 
};
a();

Why does the above code behave differently?

2 Answers

In named IIFEs, the name of the function is an implicit constant value.

Reassigning it by default will not override it nor throw you an error, but in strict mode, you can see it's actually a constant and will throw you an error:

var a = 1; 
(function a () { 
    "use strict";
    a = 2;  // throws error: Assignment to constant variable
    console.log("a:", a); 
})();

I could be wrong, but I think the below code

    /* part 1 */
    function a() { 
        a = 1;
        console.log("a1:", a); 
    };
    /* part 2 */
    function a() { 
        a = 2;
        console.log("a1:", a); 
    };
    a();
    console.log("a2:", a);

has proven that it has nothing to do with Function.name's Writable attribute.

https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function/name

Function.name is merely the name of a Function, and it has nothing to do with whether the variable itself can be rewritten.

Meanwhile, another popular explaination for this outcome is that inside the scope of "Named Function" such as function a() {...} "the variable that shares the same name with the Named Function" would point to the "Named Function."

This explaination is also wrong. Why? Because the above code outputs "a1: 2" and "a2: 2." Not only is the variable a inside the "Named Function" /* part 2 */ function a() {...} can be rewritten, in fact, the window.a is also rewritten, thus the a2 is printed 2.

That means, in fact, Named Function alone is not going to make "the variable inside its scope that shares the same name" to point to the Named Function itself. The above code is likely working as below:

    /* part 1 */
    var a = function () { 
        a = 1;
        console.log("a1:", a); 
    };
    /* part 2 */
    var a = function () { 
        a = 2;
        console.log("a1:", a); 
    };
    a();
    console.log("a2:", a);

Which means we only see it in the IIFE or assigned Named Function, such as:

    void function a() { ... }

    var a = function a() { ... }

that inside the scope of a Named Function, the variable shares the name with the Function itself would point to the Function itself (instead of the global/window).

As a matter of fact, no matter how the syntax goes, what is required is that the Named Function is not attached to the global/window. In another word, for the variable that shares the same name with it's scope master, it's scope master (a Name Function) must be in the state of "being homeless."

Related