Get all user defined window properties?

15,415

Solution 1

You would need to do the work for yourself. Read in all properties, on the first possible time you can. From that point on, you can compare the property list with your static one.

var globalProps = [ ];

function readGlobalProps() {
    globalProps = Object.getOwnPropertyNames( window );
}

function findNewEntries() {
    var currentPropList = Object.getOwnPropertyNames( window );

    return currentPropList.filter( findDuplicate );

    function findDuplicate( propName ) {
        return globalProps.indexOf( propName ) === -1;
    }
}

So now, we could go like

// on init
readGlobalProps();  // store current properties on global object

and later

window.foobar = 42;

findNewEntries(); // returns an array of new properties, in this case ['foobar']

Of course, the caveat here is, that you can only "freeze" the global property list at the time where your script is able to call it the earliest time.

Solution 2

You could also compare the window against a clean version of the window instead of trying to snapshot during runtime to compare against. I ran this in console but, you could turn it into a function.

// make sure it doesn't count my own properties
(function () {
    var results, currentWindow,
    // create an iframe and append to body to load a clean window object
    iframe = document.createElement('iframe');
    iframe.style.display = 'none';
    document.body.appendChild(iframe);
    // get the current list of properties on window
    currentWindow = Object.getOwnPropertyNames(window);
    // filter the list against the properties that exist in the clean window
    results = currentWindow.filter(function(prop) {
        return !iframe.contentWindow.hasOwnProperty(prop);
    });
    // log an array of properties that are different
    console.log(results);
    document.body.removeChild(iframe);
}());

Solution 3

This is in the same spirit as @jungy 's answer but we can do it in 3 lines:

document.body.appendChild(document.createElement('div')).innerHTML='<iframe id="temoin" style="display:none"></iframe>';

for (a in window) if (!(a in window.frames[window.frames.length-1])) console.log(a, window[a])

document.body.removeChild($$('#temoin')[0].parentNode);

First we add a hidden iframe; then we test existing variables against the standard JavaScript API in the iframe; then we remove the iframe.

To work more conveniently, it could be useful to sort the results in alphabetical order, and it's still possible in a 3 lines version:

document.body.appendChild(document.createElement('div')).innerHTML='<iframe id="temoin" style="display:none"></iframe>';

Object.keys(window).filter(a => !(a in window.frames[window.frames.length-1])).sort().forEach((a,i) => console.log(i, a, window[a]));

document.body.removeChild($$('#temoin')[0].parentNode);

And it can be packed into a bookmark:

javascript:document.body.appendChild(document.createElement('div')).innerHTML='<iframe%20id="temoin"%20style="display:none"></iframe>';Object.keys(window).filter(a=>!(a%20in%20window.frames[window.frames.length-1])).sort().forEach((a,i)=>console.log(i,a,window[a]));document.body.removeChild(document.querySelectorAll('#temoin')[0].parentNode);throw 'done';

Solution 4

I ran this in the console in ChromeDev tool and it copied all of the user defined proper

function getUserDefinedKeys() {
    const globalKeys = ["postMessage","blur","focus","close","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","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","onselectstart","onselectionchange","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","onappinstalled","onbeforeinstallprompt","crypto","indexedDB","webkitStorageInfo","sessionStorage","localStorage","chrome","onformdata","onpointerrawupdate","speechSynthesis","webkitRequestFileSystem","webkitResolveLocalFileSystemURL","openDatabase","applicationCache","caches","ondevicemotion","ondeviceorientation","ondeviceorientationabsolute","WebUIListener","cr","assert","assertNotReached","assertInstanceof","$","getSVGElement","getDeepActiveElement","findAncestorByClass","findAncestor","disableTextSelectAndDrag","isRTL","getRequiredElement","queryRequiredElement","appendParam","createElementWithClassName","ensureTransitionEndEvent","scrollTopForDocument","setScrollTopForDocument","scrollLeftForDocument","setScrollLeftForDocument","HTMLEscape","elide","quoteString","listenOnce","hasKeyModifiers","isTextInputElement"];
    return Object.fromEntries(Object.entries(window).filter(([key]) => !globalKeys.includes(key)));
}


const getCircularReplacer = () => {
  const seen = new WeakSet();
  return (key, value) => {
    if (typeof value === "object" && value !== null) {
      if (seen.has(value)) {
        return;
      }
      seen.add(value);
    }
    return value;
  };
};

copy(JSON.stringify(getUserDefinedKeys(), getCircularReplacer()));
Share:
15,415

Related videos on Youtube

GriffLab
Author by

GriffLab

Updated on June 07, 2022

Comments

  • GriffLab
    GriffLab about 2 years

    Is there a way to find out all user defined window properties and variables (global variables) in javascript?

    I tried console.log(window) but the list is endless.

    • Bergi
      Bergi almost 10 years
    • hippietrail
      hippietrail about 9 years
      @Bergi: Which answer here covers my question that was just marked as a dupe of this? Are you saying the question is a dupe even though the answers are not. Should the answer about keys() be moved from my question or are you saying that one's wrong and even though the answers here look outdated one of these is the right answer??
    • Bergi
      Bergi about 9 years
      @hippietrail: I don't see why the answers here would be outdated. (How) don't they work for you? It seems to be just what you want, if I didn't misunderstood your question.
  • bugwheels94
    bugwheels94 about 11 years
    it will also give browser defined property
  • Andreas Louv
    Andreas Louv about 11 years
    I think this would be the closest to a perfect answer .
  • Andreas Louv
    Andreas Louv about 11 years
    But maybe you should mention that Object.getOwnPropertyNames is part of the ECMAScript 5 Edition. Also filter and Array.indexOf
  • jAndy
    jAndy about 11 years
    @NULL well, I was used to mention it for the last couple of month, I feel its time to move on :)
  • GriffLab
    GriffLab about 11 years
    @jAndy definetely time to move on, I only support ie9 and above now, this is a brilliant answer thanks alot.
  • GriffLab
    GriffLab about 11 years
    @jAndy maybe put the readGlobalProps in an IIFE that way it would be called as soon as you define it?
  • jAndy
    jAndy about 11 years
    @GriffLab Yes. I guess the same way assuming that people don't worry about legacy browsers, I'm assuming they put their application logic in closured, private scopes :-)
  • hippietrail
    hippietrail about 9 years
    Does keys(window) not take care of most of the filtering?
  • hippietrail
    hippietrail about 9 years
    This won't be any use from a userscript (Greasemonkey, Tapermonkey) since I don't believe userscript are guaranteed to run before the js in the page. What would the second best method be for that case?
  • yckart
    yckart about 7 years
    @hippietrail Since you don't believe, nothing will ever be...? Believe me there's more out there, the Greasemonkey @run-at for example.
  • Bigood
    Bigood over 5 years
    Chrome's console doesn't log results properly as of nov. 18, I had to make results global then log it. Awesome code though!
  • Venryx
    Venryx about 5 years
    "it could be useful to sort the results in chronological order, and it's still possible in a 3 lines version: ..." Don't you mean alphabetical order? (chronological would mean based on time, not alphabetical/lexical sort)
  • Siltaar
    Siltaar about 5 years
    True, fixed. Thanks.
  • Trent
    Trent almost 4 years
    If your page has iframes and throws the following error, try launching chrome with the --disable-web-security flag: "Blocked a frame with origin "" from accessing a cross-origin frame."