List all js global variables used by site (not all defined!)

Javascript

Javascript Problem Overview


What is the way to list all global variables that have been used by the site? Can any browser javascript debugger do that? By used I mean READ, not changed/added. Detect iframe ones, would be nice too.

PLEASE NOTE: I need to get a list of global variables "touched" by site. Not all of them or added ones or edited ones, the ones that were used anywhere in the site scripts.

Javascript Solutions


Solution 1 - Javascript

In Chrome, go to Dev tools and open the console. Then type in the following:

Object.keys( window );

This will give you an Array of all the global variables.

EDIT

After searching on Google a bit, I found a way. You will need firefox and the jslinter addon.

Once setup, open jslinter and go to Options->check everything on the left column except "tolerate unused parameters".

Then run jslinter on the webpage and scroll down in the results. You will have a list of unused variables (global and then local to each function).

Now run Object.keys(window); in the console and compare the results from both to figure out which ones are used.

Solution 2 - Javascript

This one-liner will get you pretty close, and does not require installing anything additional, or running code before the page loads:

Object.keys(window).filter(x => typeof(window[x]) !== 'function' &&
  Object.entries(
    Object.getOwnPropertyDescriptor(window, x)).filter(e =>
      ['value', 'writable', 'enumerable', 'configurable'].includes(e[0]) && e[1]
    ).length === 4)

It filters Object.keys(window) based on three principles:

  1. Things that are null or undefined are usually not interesting to look at.
  2. Most scripts will define a bunch of event handlers (i.e. functions) but they are also usually not interesting to dump out.
  3. Properties on window that are set by the browser itself, are usually defined in a special way, and their property descriptors reflect that. Globals defined with the assignment operator (i.e. window.foo = 'bar') have a specific-looking property descriptor, and we can leverage that. Note, if the script defines properties using Object.defineProperty with a different descriptor, we'll miss them, but this is very rare in practice.

Solution 3 - Javascript

What i did was. I found a page with as little JavaScript / Frameworks as possible, logged all their keys in array. Then iterated all the keys on the new page and logged only those which were not listed in the previous site. You can try it or use my code snippet

var ks = ["postMessage","blur","focus","close","frames","self","window","parent","opener","top","length","closed","location","document","origin","name","history","locationbar","menubar","personalbar","scrollbars","statusbar","toolbar","status","frameElement","navigator","customElements","external","screen","innerWidth","innerHeight","scrollX","pageXOffset","scrollY","pageYOffset","screenX","screenY","outerWidth","outerHeight","devicePixelRatio","clientInformation","screenLeft","screenTop","defaultStatus","defaultstatus","styleMedia","onanimationend","onanimationiteration","onanimationstart","onsearch","ontransitionend","onwebkitanimationend","onwebkitanimationiteration","onwebkitanimationstart","onwebkittransitionend","isSecureContext","onabort","onblur","oncancel","oncanplay","oncanplaythrough","onchange","onclick","onclose","oncontextmenu","oncuechange","ondblclick","ondrag","ondragend","ondragenter","ondragleave","ondragover","ondragstart","ondrop","ondurationchange","onemptied","onended","onerror","onfocus","oninput","oninvalid","onkeydown","onkeypress","onkeyup","onload","onloadeddata","onloadedmetadata","onloadstart","onmousedown","onmouseenter","onmouseleave","onmousemove","onmouseout","onmouseover","onmouseup","onmousewheel","onpause","onplay","onplaying","onprogress","onratechange","onreset","onresize","onscroll","onseeked","onseeking","onselect","onstalled","onsubmit","onsuspend","ontimeupdate","ontoggle","onvolumechange","onwaiting","onwheel","onauxclick","ongotpointercapture","onlostpointercapture","onpointerdown","onpointermove","onpointerup","onpointercancel","onpointerover","onpointerout","onpointerenter","onpointerleave","onafterprint","onbeforeprint","onbeforeunload","onhashchange","onlanguagechange","onmessage","onmessageerror","onoffline","ononline","onpagehide","onpageshow","onpopstate","onrejectionhandled","onstorage","onunhandledrejection","onunload","performance","stop","open","alert","confirm","prompt","print","requestAnimationFrame","cancelAnimationFrame","requestIdleCallback","cancelIdleCallback","captureEvents","releaseEvents","getComputedStyle","matchMedia","moveTo","moveBy","resizeTo","resizeBy","getSelection","find","webkitRequestAnimationFrame","webkitCancelAnimationFrame","fetch","btoa","atob","setTimeout","clearTimeout","setInterval","clearInterval","createImageBitmap","scroll","scrollTo","scrollBy","onappinstalled","onbeforeinstallprompt","crypto","ondevicemotion","ondeviceorientation","ondeviceorientationabsolute","indexedDB","webkitStorageInfo","sessionStorage","localStorage","chrome","visualViewport","speechSynthesis","webkitRequestFileSystem","webkitResolveLocalFileSystemURL","addEventListener", "removeEventListener", "openDatabase", "dispatchEvent"]
var newKs = []
for (key in window) {
    if(ks.indexOf(key) == -1 && key !== "ks" && key !=="newKs") {
        newKs.push(key);
    }
}
console.log(newKs);

Solution 4 - Javascript

You could try to use getters for that, which you create for all existing global variables. Run this before the page is started:

Object.keys(window) // or
Object.getOwnPropertyNames(window).concat(
  Object.getOwnPropertyNames(Object.getPrototypeOf(window))
) // or whatever
.forEach(function(name) {
    var d = Object.getOwnPropertyDescriptor(window, name),
        def = Object.defineProperty,
        log = console.log.bind(console);
    if (d && !d.configurable)
        return log("cannot detect accessing of "+name);
    def(window, name, {
        configurable: true,
        get: function() {
            log("window."+name+" was used by this page!");
            if (d) {
                def(window, name, d);
                return d.get ? d.get() : d.value;
            } else { // it was not an own property
                delete window[name];
                return window[name];
            }
        },
        set: function(x) {
            log("Ugh, they're overwriting window."+name+"! Something's gonna crash.");
        }
    });
});

Of course property descriptors etc. are not compatible with older browsers. And notice that there are some global variables / window properties that might not be programmatically listable (like on* handlers), if you need them you will have to explicitly list them in the array. See the related questions https://stackoverflow.com/q/10374462 and https://stackoverflow.com/q/10931833 for that.

Yet I guess running a code coverage tool that whinges about undeclared global variables, like @stackErro suggested, is more helpful.

Solution 5 - Javascript

Since this question is the first in google when searching for a way how to list global javascript variables, I will add my own answer for that. Sometimes you need to list global variables to see if your code does not have a variable leaked outside the scope (defined without 'var'). For that, use this in the debug console:

(function ()
{
   var keys=Object.keys( window );
   for (var i in keys)
   {
      if (typeof window[keys[i]] != 'function')
      console.log(keys[i], window[keys[i]]);
   }
})();

It will list the standard global variables, like window, document, location, etc. Those are just few. So you can find your leaked vars in the list easily.

Solution 6 - Javascript

copy and paste the following code into your javascript console

var keys = Object.getOwnPropertyNames( window ),
    value;

for( var i = 0; i < keys.length; ++i ) {
    value = window[ keys[ i ] ];
    console.log( value );
}

all credits to RightSaidFred (https://stackoverflow.com/questions/8369338/javascript-dumping-all-global-variables)

i hope that helped you

Solution 7 - Javascript

Easy way to list your globals I use sometimes. First put this code as early as possible, before any of your scripts executed.

var WINDOW_PROPS = Object.keys(window);

Then at the moment when you need to discover your globals just do something like this:

var GLOBALS = Object.keys(window)
    // filter the props which your code did not declare
    .filter(prop => WINDOW_PROPS.indexOf(prop) < 0)
    // prettify output a bit :) It's up to you...
    .map(prop => `${typeof window[prop]} ${prop} ${window[prop]}`)
    // sort by types and names to find easier what you need
    .sort();

console.log(GLOBALS.join("\n"));

I've used some ES6 features here to shorten the code. It's still not good for production, but good enough for debug purposes and should work in modern browsers.

Solution 8 - Javascript

Take the list from Object.keys(window), remove the global variables the browser generates by default, you are left with only the global variables you declared on page. Note: functions you declared also count as global variables.

const listGlobal = ()=> { //for debugging purposes
	//put this function inside your html or javascript. Go to the html page.
	//In chrome console type listGlobal(); to see list of global vars

	//Array of global variables that exist in chrome browser by default
	var stdChromeVars = ["parent","opener","top","length","frames","closed","location","self","window","document","name","customElements","history","locationbar","menubar","personalbar","scrollbars","statusbar","toolbar","status","frameElement","navigator","origin","external","screen","innerWidth","innerHeight","scrollX","pageXOffset","scrollY","pageYOffset","visualViewport","screenX","screenY","outerWidth","outerHeight","devicePixelRatio","clientInformation","screenLeft","screenTop","defaultStatus","defaultstatus","styleMedia","onsearch","isSecureContext","onabort","onblur","oncancel","oncanplay","oncanplaythrough","onchange","onclick","onclose","oncontextmenu","oncuechange","ondblclick","ondrag","ondragend","ondragenter","ondragleave","ondragover","ondragstart","ondrop","ondurationchange","onemptied","onended","onerror","onfocus","onformdata","oninput","oninvalid","onkeydown","onkeypress","onkeyup","onload","onloadeddata","onloadedmetadata","onloadstart","onmousedown","onmouseenter","onmouseleave","onmousemove","onmouseout","onmouseover","onmouseup","onmousewheel","onpause","onplay","onplaying","onprogress","onratechange","onreset","onresize","onscroll","onseeked","onseeking","onselect","onstalled","onsubmit","onsuspend","ontimeupdate","ontoggle","onvolumechange","onwaiting","onwebkitanimationend","onwebkitanimationiteration","onwebkitanimationstart","onwebkittransitionend","onwheel","onauxclick","ongotpointercapture","onlostpointercapture","onpointerdown","onpointermove","onpointerup","onpointercancel","onpointerover","onpointerout","onpointerenter","onpointerleave","onselectstart","onselectionchange","onanimationend","onanimationiteration","onanimationstart","ontransitionend","onafterprint","onbeforeprint","onbeforeunload","onhashchange","onlanguagechange","onmessage","onmessageerror","onoffline","ononline","onpagehide","onpageshow","onpopstate","onrejectionhandled","onstorage","onunhandledrejection","onunload","performance","stop","open","alert","confirm","prompt","print","queueMicrotask","requestAnimationFrame","cancelAnimationFrame","captureEvents","releaseEvents","requestIdleCallback","cancelIdleCallback","getComputedStyle","matchMedia","moveTo","moveBy","resizeTo","resizeBy","scroll","scrollTo","scrollBy","getSelection","find","webkitRequestAnimationFrame","webkitCancelAnimationFrame","fetch","btoa","atob","setTimeout","clearTimeout","setInterval","clearInterval","createImageBitmap","close","focus","blur","postMessage","onappinstalled","onbeforeinstallprompt","crypto","indexedDB","webkitStorageInfo","sessionStorage","localStorage","chrome","applicationCache","onpointerrawupdate","trustedTypes","speechSynthesis","webkitRequestFileSystem","webkitResolveLocalFileSystemURL","openDatabase","caches","ondevicemotion","ondeviceorientation","ondeviceorientationabsolute"];


	//load the current list of global variables
	let thisdocVars = Object.keys(window);

	//remove from the current list any variables that's in the browser default list
	stdChromeVars.forEach(DelFunc);
		function DelFunc(item) {
			thisdocVars.forEach((e,i)=>{if(e==item){thisdocVars.splice(i, 1);}});
		}

	//separate variables into functions and variables
	let thisdocfunc = [];
	let thisdocvar = [];
	thisdocVars.forEach((e)=>{if(typeof window[e]=="function"){thisdocfunc.push(e);}else{thisdocvar.push(e);}});
	console.log("Global Functions:\n" + thisdocfunc);
	console.log("Global Variables:\n" + thisdocvar);
	//Ctrl+Shift+i to see console in chrome
}

Solution 9 - Javascript

You can try using JetBrains PhpStorm that's what I do, you can get a trial of 30 days for free for any system. Then you check on JSLint or JSHint or both I cant remember and then all your unused variables are underlined, highlighted with different color (according to theme) and visible on the scrollbar and when you hover over them it says unused variable;

EDIT: I think community version is free now.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFlash ThunderView Question on Stackoverflow
Solution 1 - JavascriptstackErrView Answer on Stackoverflow
Solution 2 - Javascriptjd20View Answer on Stackoverflow
Solution 3 - JavascriptViktor VeselýView Answer on Stackoverflow
Solution 4 - JavascriptBergiView Answer on Stackoverflow
Solution 5 - JavascriptTomas MView Answer on Stackoverflow
Solution 6 - JavascriptUNXView Answer on Stackoverflow
Solution 7 - JavascriptЕвгений СавичевView Answer on Stackoverflow
Solution 8 - JavascriptMikeView Answer on Stackoverflow
Solution 9 - JavascriptJacek PietalView Answer on Stackoverflow