39

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.

lucapette
  • 20,564
  • 6
  • 65
  • 59
Duck
  • 34,902
  • 47
  • 248
  • 470

8 Answers8

48
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 );
}
Community
  • 1
  • 1
RightSaidFred
  • 11,209
  • 35
  • 35
  • 7
    You can also use `Object.getOwnPropertyNames( window )` for non-enumerables – Raynos Dec 03 '11 at 17:12
  • 1
    On Chrome, some of `window`'s properties inherit from `Window.prototype` and `Window`. They're accessible as globals, but you'll need to concat together `Object.getOwnPropertyNames` results on `window`, `Window`, and `Window.prototype` – Matthew Sep 29 '15 at 13:13
  • also see this answer: http://stackoverflow.com/a/17246535/4040525 Combining both of them worked great for me – Sourav Ghosh Jan 24 '17 at 11:24
  • it does not work. `ReferenceError: window is not defined` – user5359531 Mar 01 '22 at 20:04
5

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).

robocat
  • 5,293
  • 48
  • 65
3

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.

pimvdb
  • 151,816
  • 78
  • 307
  • 352
2

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.

Remek Ambroziak
  • 790
  • 8
  • 11
1

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] + '!');
    }
}
Ry-
  • 218,210
  • 55
  • 464
  • 476
  • I know it is a fairly old answer, but `'window.webkitStorageInfo' is deprecated. Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead.` – Jelmer Dec 31 '13 at 08:46
1

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

function globals() { return this; }

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

c-smile
  • 26,734
  • 7
  • 59
  • 86
  • 2
    Not strict mode compliant, by the way :) – Ry- Dec 03 '11 at 17:12
  • 1
    Um... because it's true? Take a look at this on an ES5-compatible browser: http://jsfiddle.net/G95gQ/ – Ry- Dec 03 '11 at 17:14
  • 2
    @c-smile In strict mode when there is no context, `this` is `null`. It's not the global object. – HoLyVieR Dec 03 '11 at 17:15
  • 3
    @HoLyVieR: And finally, to be nitpicky, it's not `null`, it's `undefined` :) – Ry- Dec 03 '11 at 17:16
  • Isn't this just the same as using `this` globally? `this === globals()` evaluates to `true` in both the Firefox and Node consoles because `this` globally is just the [global object](https://developer.mozilla.org/en-US/docs/Glossary/Global_object). – ChrisCrossCrash May 01 '21 at 13:46
0

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

BugaBuga
  • 489
  • 4
  • 10
0

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.

seanCodes
  • 553
  • 7
  • 10