Get Global Variables with JavaScript

By  on  

Updated 9/1/2015: My original method, keys(window) gave unhelpful results in browsers other than Chrome. I've updated this post with a more reliable method.

JavaScript globals are considered bad.  And as a contributor to the MooTools project, I've heard this on a daily basis for the better part of a decade.  MooTools got knocked for extending natives but also for placing objects in the global space, like Browser and $$.  I find the "global vars are terrible" philosophy a bit funny since even jQuery and JavaScript loaders use a global variable.

Intentional globals aside, leaking global variables is bad practice and a result of sloppy coding.  So how can we see what properties are custom within the global namespace?  It's easier than you think:

// UPDATE:  This method is too naive
// Returns an array of window property names
//keys(window);

// Inject an iframe and compare its `contentWindow` properties to the global window properties
(function() {
	var iframe = document.createElement('iframe');
	iframe.onload = function() {
		var iframeKeys = Object.keys(iframe.contentWindow);
		Object.keys(window).forEach(function(key) {
			if(!(key in iframeKeys)) {
				console.log(key);
			}
		});
	};
	iframe.src = 'about:blank';
	document.body.appendChild(iframe);
})();

You will see some variables there that you know you didn't set, like window, document, top, and location, but the others will have been leaked (or intentional) globals set by custom JavaScript code!

Recent Features

  • By
    LightFace:  Facebook Lightbox for MooTools

    One of the web components I've always loved has been Facebook's modal dialog.  This "lightbox" isn't like others:  no dark overlay, no obnoxious animating to size, and it doesn't try to do "too much."  With Facebook's dialog in mind, I've created LightFace:  a Facebook lightbox...

  • By
    Vibration API

    Many of the new APIs provided to us by browser vendors are more targeted toward the mobile user than the desktop user.  One of those simple APIs the Vibration API.  The Vibration API allows developers to direct the device, using JavaScript, to vibrate in...

Incredible Demos

  • By
    spellcheck Attribute

    Many useful attributes have been provided to web developers recently:  download, placeholder, autofocus, and more.  One helpful older attribute is the spellcheck attribute which allows developers to  control an elements ability to be spell checked or subject to grammar checks.  Simple enough, right?

  • By
    Build a Calendar Using PHP, XHTML, and CSS

    One of the website features my customers love to provider their web users is an online dynamic calendar. An online calendar can be used for events, upcoming product specials, memos, and anything else you can think of. I've taken some time to completely...

Discussion

  1. GoogleAnalyticsObject :)

  2. Darren

    Am I missing something? All I get is:

    ReferenceError: Can't find variable: keys
    
  3. http://caniuse.com/#search=keys
    You may also use:

    Object.keys(window).join(' ')
  4. Hamburger

    Firefox 40.0.3 and windows 7 do not knows keys: keys is not defined

  5. MaxArt

    keys is a console command for Chrome. It should be equivalent to Object.keys, though.
    But, overall, if you don’t want your variables to be leaked, the best recommendation is to use strict mode.

  6. thinsoldier

    Firefox returns an array of 186 items and Chrome returns an array of 23 items. I think more standardization work is needed.

  7. All: I’ve updated with a more helpful method!

    • MaxArt

      Oh, that’s actually nice.
      I suggest removing the iframe from the document after logging the differences.

  8. key in iframeKeys may be wrong, iframeKeys.indexOf(key) > -1 works fine

  9. So, that is the best option to not use a global variable ?

  10. Valtteri

    This seems to work better:

    {
    	let props = []
    	let iframe = document.createElement('iframe')
    	document.body.append(iframe)
    	for (let prop of Object.keys(window)) {
    		if (!(prop in iframe.contentWindow)) props.push(prop)
    	}
    	console.log(props)
    	iframe.remove()
    }
    
  11. Just an ever-so-slight improvement on Valterri’s concise suggestion:

    {
    	let props = []
    	let iframe = document.createElement('iframe')
    	document.body.append(iframe)
    	for (let prop of Object.keys(window)) {
    		if (!(prop in iframe.contentWindow)) props.push(prop)
    	}
    	console.table(props.sort())
    	iframe.remove()
    }
    
    
  12. {
        let props = [],
    	    iframe = document.createElement('iframe');
    
        document.body.append(iframe)
    
    	for (let prop of Object.keys(window)) 
    		if (!(prop in iframe.contentWindow)) props.push(prop)
    	
    	console.table(props.sort())
    	iframe.remove()
    }
    
  13. Jon

    Is there supposed to be an iframe somewhere automatically, or does it have to be triggered?

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!