Variables in the Global Space

Excerpt

How can you find out about already existing global variables ?

Summary: you can - but only partially.

I had this question while analyzing a complex web site and application with several independent implemented parts inside and some effects that "smell" for being caused by affecting each other.

So how do global variables work.

The global scope and `var` variables

Defining a global variable using the `var` statement is using a global scope. This scope is available as an Object using the `globalThis` and in browsers the `window` Object.

In global script blocks in the browser the 3 statements actually do the same:


var varBucket = "HelloBucket";
window.varBucket = "HelloBucket";
globalThis.varBucket = "HelloBucket";
    

To test this, just have a look in the console for the output of the following script:


var varBucket = 'HelloBucket1';
console.log(varBucket, window.varBucket, globalThis.varBucket, globalThis['varBucket'], eval('varBucket'));

window.varBucket = 'HelloBucket2';
console.log(varBucket, window.varBucket, globalThis.varBucket, globalThis['varBucket'], eval('varBucket'));

globalThis.varBucket = 'HelloBucket3';
console.log(varBucket, window.varBucket, globalThis.varBucket, globalThis['varBucket'], eval('varBucket'));
    

creating the following output in the console:

HelloBucket1 HelloBucket1 HelloBucket1 HelloBucket1 HelloBucket1
HelloBucket2 HelloBucket2 HelloBucket2 HelloBucket2 HelloBucket2
HelloBucket3 HelloBucket3 HelloBucket3 HelloBucket3 HelloBucket3
    

The global scope and `let` variables

A lot of articles on the internet suggest using `let` or `const` instead of `var`. Using the same script above with `let` based variable definitions shows that the globalThis object will not reflect these variables:


let letBucket = 'HelloBucket1';
console.log(letBucket, window.letBucket, globalThis.letBucket, globalThis['letBucket'], eval('letBucket'));

letBucket = 'HelloBucket2-a';
window.letBucket = 'HelloBucket2-b';
console.log(letBucket, window.letBucket, globalThis.letBucket, globalThis['letBucket'], eval('letBucket'));

globalThis.letBucket = 'HelloBucket3';
console.log(letBucket, window.letBucket, globalThis.letBucket, globalThis['letBucket'], eval('letBucket'));

creating the following output in the console:

HelloBucket1 undefined undefined undefined HelloBucket1
HelloBucket1 HelloBucket2 HelloBucket2 HelloBucket2 HelloBucket1
HelloBucket1 HelloBucket3 HelloBucket3 HelloBucket3 HelloBucket1
    

The globalThis is obviously not including these global variables.

List defined global variables

So the following trick only works for the `var` based variables:


// analyze all attributes of globalThis
const keys = {};

const globalThisKeys = Object.keys(globalThis);
globalThisKeys.forEach(k => {
  keys[k] = { key: k, type: typeof globalThis[k] };
});
  
// list of standard attributes on the window object
const stdWindowKeys = 'window,self,document,name,location,
  (cut here),
  webkitResolveLocalFileSystemURL'.split(',');

stdWindowKeys.forEach(k => {
  delete keys[k];
});

console.table(keys);
     

Have a look to the console output to see the result. Happy debugging...

See Also

Tags

JavaScript