IIFE strange behavior linked to variables declared with let or var

35 Views Asked by At

I try to understand why the variable 'Permissions' will be typeof 'function' when Permissions declared with var but typeof 'object' when declared with let (which is the excepted behavior)

With 'var' - Permissions is typeof 'function'

var Permissions;

(function (Permissions) {
    Permissions[Permissions["ADMIN"] = 0] = "ADMIN";
    Permissions[Permissions["READ_ONLY"] = 1] = "READ_ONLY";
})(Permissions || (Permissions = {}));

console.log(typeof Permissions);

With 'let' - Permissions is typeof 'object'

let Permissions;

(function (Permissions) {
    Permissions[Permissions["ADMIN"] = 0] = "ADMIN";
    Permissions[Permissions["READ_ONLY"] = 1] = "READ_ONLY";
})(Permissions || (Permissions = {}));

console.log(typeof Permissions);

I excepted both scenario to be 'object'. why using 'var' Permissions is typeof 'function'?

1

There are 1 best solutions below

0
Alexander Nenashev On BEST ANSWER

Declaring a variable with var in a global scope makes it a property of window. Since you haven't initialized it, it's actually pointing to the existing window.Permissions property, which is a constructor of navigator.permissions.

let works differently and declares a separate variable in the current scope:

console.log(Permissions);
console.log(navigator.permissions.__proto__ === Permissions.prototype);

var test = 'test';
console.log(window.test);

If you put your var into a function scope, it would work like let:

(function(){

  var Permissions;

  (function (Permissions) {
      Permissions[Permissions["ADMIN"] = 0] = "ADMIN";
      Permissions[Permissions["READ_ONLY"] = 1] = "READ_ONLY";
  })(Permissions || (Permissions = {}));

  console.log(typeof Permissions);

})();

Also works as let in a module scope:

<script type="module">

var Permissions;

(function (Permissions) {
    Permissions[Permissions["ADMIN"] = 0] = "ADMIN";
    Permissions[Permissions["READ_ONLY"] = 1] = "READ_ONLY";
})(Permissions || (Permissions = {}));

console.log(typeof Permissions);

</script>

With this and other many problems inherited to var I treat var as legacy and dangerous and prohibit it with ESLint.