Search code examples
javascriptecmascript-6scopestrict-modejavascript-function-declaration

Does hoisting of functions behave differently when strict mode is off?


Here are two similiar codes except for the "use strict" part

    "use strict"
    { function a() {
        return 1;
      }
    }
    function a() {
        return 2;
    }
    console.log(a()); 

in this case console returns 2 because as I can understand in strict mode functions are scoped to their nearest enclosing block, and thus calling a() will trigger the function that has been defined in a global scope but when I try to execute the same code without turning on strict mode it will produce a completely different output that is 1

    { function a() {
           return 1;
      }
    }
    function a() {
           return 2;
    }
    console.log(a());

I wonder why cause I expected console would still return 2, as I thought in non strict mode functions aren't scoped to their enclosing block, so the second declaration of function with the same name would override the previous one and eventually we would still get 2, but for some reason it doesn't work that way without strict mode?

Probably it's somehow related to usuing those {} that the first function is scoped to but I'm not really sure


Solution

  • tl;dr: In non-strict mode, handling of function declarations in blocks is inconsistent before JS engines. Don't do that.

    From MDN:

    Block-scoped function declarations

    The JavaScript language specification, since its start, had not allowed function declarations nested in block statements. However, it was so intuitive that most browsers implemented it as an extension grammar. Unfortunately, the implementations' semantics diverged, and it became impossible for the language specification to reconcile all implementations. Therefore, block-scoped function declarations are only explicitly specified in strict mode (whereas they were once disallowed in strict mode), while sloppy mode behavior remains divergent among browsers.