Javascript - dumping all global variables

Is there a way in Javascript to get a list or dump the contents of all global variables declared by Javascript/jQuery script on a page? I am particularly interested in arrays. If I can get the array names, it will be enough to me. Seeing its values is a bonus.

Answers:

Answer
Object.keys( window );

This will give you an Array of all enumerable properties of the window object, (which are global variables).

For older browsers, include the compatibility patch from MDN.


To see its values, then clearly you'll just want a typical enumerator, like for-in.


You should note that I mentioned that these methods will only give you enumerable properties. Typically those will be ones that are not built-in by the environment.

It is possible to add non-enumerable properties in ES5 supported browsers. These will not be included in Object.keys, or when using a for-in statement.


As noted by @Raynos, you can Object.getOwnPropertyNames( window ) for non-enumerables. I didn't know that. Thanks @Raynos!

So to see the values that include enumerables, you'd want to do this:

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

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

Since all global variables are properties of the window object, you can get them using:

for(var key in window) { // all properties
    if(Array.isArray(window[key])) { // only arrays
        console.log(key, window[key]); // log key + value
    }
}

Since all default/inherited properties are not plain arrays (mostly host objects or functions), the Array.isArray check is sufficient.

Answer

To get "globals" object you can use this function:

function globals() { return this; }

Here is the test: http://jsfiddle.net/EERuf/

Answer

window is the global object in a browser, and you can use a for..in loop to loop through its properties:

if(!Array.isArray) {
    Array.isArray = function(obj) {
        return Object.prototype.toString.call(obj) === '[object Array]';
    };
}

for(var x in window) {
    if(Array.isArray(window[x])) {
        console.log('Found array ' + x + ' in ' + window + ', it has the value ' + window[x] + '!');
    }
}
Answer

You can use npm package called get-globals. It compares properties of window with fresh-created iframe to print only variables declared by dev(s), not browser vendor.

Answer

Greasymonkey script to get leaked globals

// ==UserScript==
// @name        SCI
// @namespace   ns
// @version     1
// @grant       none
// @run-at      document-start
// ==/UserScript==
console.log('SCI loaded');
var SCI = window.SCI = {
        defprops: [],
        collect: function(){
            var wprops = [];
            for(var prop in window){
                wprops.push(prop);
            }
            return wprops;
        },
        collectDef: function(){
            this.defprops = this.collect(); 
        },
        diff: function(){
            var def = this.defprops,
                cur = this.collect();
            var dif = [];
            for(var i = 0; i < cur.length; i++){
                var p = cur[i];
                if(def.indexOf(p) === -1){
                    dif.push(p);
                }
            }
            return dif;
        },
        diffObj: function(){
            var diff = this.diff();
            var dobj = {};
            for (var i = 0; i < diff.length; i++){
                var p = diff[i];
                dobj[p]=window[p];
            }
            return dobj;

        }
};
SCI.collectDef();

To use run in console SCI.diff() to get list of names or SCI.diffObj() to get object with variables

Answer

The following function only dumps global variables that have been added to the window object:

(function(){
    //noprotect <- this comment prevents jsbin interference
    var windowProps = function() {
        // debugger;
        var result = {};
        for (var key in window) {
            if (Object.prototype.hasOwnProperty.call(window, key)) {
                if ((key|0) !== parseInt(key,10)) {
                    result[key] = 1;
                }
            }
        }
        window.usedVars = result;
    };

    var iframe = document.createElement('iframe');
    iframe.style.display = 'none';
    iframe.src = 'about:blank'; 
    document.body.appendChild(iframe);
    var fwin = iframe.contentWindow;
    var fdoc = fwin.document;
    fdoc.open('text/html','replace');
    fdoc.write('<!DOCTYPE html><body><script>window.onload = ' + windowProps.toString() + '<\u002Fscript>');
    fdoc.close();

    var button = document.createElement('input');
    button.type = 'button';
    button.value = 'go';
    document.body.appendChild(button);
    button.onclick = function() {
        var clean = fwin.usedVars;
        windowProps();
        var dirty = window.usedVars;
        for (var key in clean) {
            delete dirty[key];
        }
        for (var variable in dirty) {
            var div = document.createElement('div');
            div.textContent = variable;
            document.body.appendChild(div);     
        }
        document.body.removeChild(button);
        document.body.removeChild(iframe);
    };
})();

It works by using an iframe to get a clean list of global window variables, then comparing that with the list of global variables in the current window. It uses a button because the iframe runs asynchronously. The code uses a global variable because that makes the code easier to understand.

You can see it working here or here, although note that these examples show many global variables "leaked" by jsbin itself (different depending on which link you use).

Answer

Here’s a simple, more modern snippet that logs an object with the globals and their values (rather than just the global variable names), which is usually what I’m looking for when debugging:

(function () {
    const iframe = document.createElement('iframe')
    iframe.setAttribute('hidden', '')
    iframe.src = 'about:blank'
    iframe.onload = function () {
        // Iterate through the properties of the current `window` and reduce the output
        // to only properties that are not in the iframe’s `window`.
        console.debug(Object.entries(window).reduce((reducedObj, [property, value]) => {
            // Check if the property does not exist in the iframe and if so, add it to
            // the output object.
            if (! (property in iframe.contentWindow))
                reducedObj[property] = value
            return reducedObj
        }, {})))
        // Clean up the iframe by removing it from the DOM.
        iframe.remove()
    }
    // Append the iframe to the DOM to kick off loading.
    document.body.append(iframe)
})()

Tip: You can also swap 'about:blank' with window.location to get only the globals set since the page was first loaded.

This uses an iframe to determine which properties to ignore like robocat’s answer, but it’s based on David Walsh’s solution.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.