DEV Community

Discussion on: How to avoid namespace pollution in Javascript

 
peerreynders profile image
peerreynders • Edited
  • It's only top level var and function declarations in inline JavaScript that pollute the global object (typically prevented with an IIFE). This doesn't happen in type="module" or ECMAScript modules - those names are "module global" but do not create properties on the global object.
  • const and let are block scoped so they don't affect the global object.
  • In modules you can still alter the global object via any name that is bound to it (provided that part isn't read-only). So window['myVariable'] = 'NewValue'; is possible.
  • Imported names are "module global" but do not create properties on the global object

<!DOCTYPE html>
<!-- index.html -->
<html>
  <head>
    <title>Top level Variables</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
  </head>
  <body>
    <p>Check the (web) developer tools console</p>
    <script type="module">
      // global names:
      //
      // `window` - browser window only
      // `self` - browser window & web worker (including service worker)
      // `global` - Node.js only
      // `globalThis` - browser window & web worker & Node.js

      console.log('TYPE: inline module - defer by default');

      // console.log(noVariable); // Uncaught ReferenceError: noVariable is not defined
      console.assert(globalThis.hasOwnProperty('varModVariable') === false);
      console.assert(typeof varModVariable === 'undefined');
      var varModVariable = 'varModValue';
      console.assert(globalThis.hasOwnProperty('varModVariable') === false);
      console.assert(varModVariable === 'varModValue');
      console.assert(typeof globalThis.varModVariable === 'undefined');
      console.assert(typeof self.varModVariable === 'undefined');
      console.assert(typeof window.varModVariable === 'undefined');

      // console.log(constVariable); // Uncaught ReferenceError: Cannot access 'constVariable' before initialization
      console.assert(globalThis.hasOwnProperty('constVariable') === false);
      const constVariable = 'constValue';
      console.assert(globalThis.hasOwnProperty('constVariable') === false);
      console.assert(constVariable === 'constValue');

      // console.log(letVariable); // Uncaught ReferenceError: Cannot access 'letVariable' before initialization
      console.assert(globalThis.hasOwnProperty('letVariable') === false);
      let letVariable = 'letValue';
      console.assert(globalThis.hasOwnProperty('letVariable') === false);
      console.assert(letVariable === 'letValue'); // "letValue"

      console.assert(globalThis.hasOwnProperty('myModGlobal') === false);
      globalThis.myModGlobal = 'globalModValue';
      console.assert(globalThis.hasOwnProperty('myModGlobal') === true);
      console.assert(globalThis['myModGlobal'] === 'globalModValue');
      console.assert(globalThis.myModGlobal === 'globalModValue');
      console.assert(self.myModGlobal === 'globalModValue');
      console.assert(window.myModGlobal === 'globalModValue');
      console.assert(myModGlobal === 'globalModValue');
    </script>
    <script>
      (function () {
        console.log(
          'TYPE: inline text/javascript + immediately invoked function expression (IIFE)'
        );
        // console.log(noVariable); // Uncaught ReferenceError: noVariable is not defined
        console.assert(globalThis.hasOwnProperty('varIifeVariable') === false);
        console.assert(typeof varIifeVariable === 'undefined');
        var varIifeVariable = 'varIifeValue';
        console.assert(globalThis.hasOwnProperty('varIifeVariable') === false);
        console.assert(varIifeVariable === 'varIifeValue');
        console.assert(typeof globalThis.varIifeVariable === 'undefined');
        console.assert(typeof self.varIifeVariable === 'undefined');
        console.assert(typeof window.varIifeVariable === 'undefined');

        // console.log(constVariable); // Uncaught ReferenceError: Cannot access 'constVariable' before initialization
        console.assert(globalThis.hasOwnProperty('constVariable') === false);
        const constVariable = 'constValue';
        console.assert(globalThis.hasOwnProperty('constVariable') === false);
        console.assert(constVariable === 'constValue');

        // console.log(letVariable); // Uncaught ReferenceError: Cannot access 'letVariable' before initialization
        console.assert(globalThis.hasOwnProperty('letVariable') === false);
        let letVariable = 'letValue';
        console.assert(globalThis.hasOwnProperty('letVariable') === false);
        console.assert(letVariable === 'letValue'); // "letValue"

        console.assert(globalThis.hasOwnProperty('myIifeGlobal') === false);
        globalThis.myIifeGlobal = 'globalIifeValue';
        console.assert(globalThis.hasOwnProperty('myIifeGlobal') === true);
        console.assert(globalThis['myIifeGlobal'] === 'globalIifeValue');
        console.assert(globalThis.myIifeGlobal === 'globalIifeValue');
        console.assert(self.myIifeGlobal === 'globalIifeValue');
        console.assert(window.myIifeGlobal === 'globalIifeValue');
        console.assert(myIifeGlobal === 'globalIifeValue');
      })();
    </script>
    <script>
      console.log('TYPE: inline text/javascript');

      // console.log(noVariable); // Uncaught ReferenceError: noVariable is not defined
      console.assert(globalThis.hasOwnProperty('varVariable') === true);
      console.assert(typeof varVariable === 'undefined');
      var varVariable = 'varValue';
      console.assert(globalThis.hasOwnProperty('varVariable') === true);
      console.assert(varVariable === 'varValue');
      console.assert(globalThis.varVariable === 'varValue');
      console.assert(self.varVariable === 'varValue');
      console.assert(window.varVariable === 'varValue');

      // console.log(constVariable); // Uncaught ReferenceError: Cannot access 'constVariable' before initialization
      console.assert(globalThis.hasOwnProperty('constVariable') === false);
      const constVariable = 'constValue';
      console.assert(globalThis.hasOwnProperty('constVariable') === false);
      console.assert(constVariable === 'constValue');

      // console.log(letVariable); // Uncaught ReferenceError: Cannot access 'letVariable' before initialization
      console.assert(globalThis.hasOwnProperty('letVariable') === false);
      let letVariable = 'letValue';
      console.assert(globalThis.hasOwnProperty('letVariable') === false);
      console.assert(letVariable === 'letValue'); // "letValue"

      console.assert(globalThis.hasOwnProperty('myGlobal') === false);
      globalThis.myGlobal = 'globalValue';
      console.assert(globalThis.hasOwnProperty('myGlobal') === true);
      console.assert(globalThis['myGlobal'] === 'globalValue');
      console.assert(globalThis.myGlobal === 'globalValue');
      console.assert(self.myGlobal === 'globalValue');
      console.assert(window.myGlobal === 'globalValue');
      console.assert(myGlobal === 'globalValue');
    </script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode