Получить все свойства окна, определенные пользователем?

Есть ли способ узнать все определенные пользователем свойства окна и переменные (глобальные переменные) в javascript?

Я пробовал console.log(window), но список бесконечен.


person GriffLab    schedule 22.06.2013    source источник
comment
comment
@Bergi: Какой ответ здесь охватывает мой вопрос, который был помечен как обман? Вы говорите, что вопрос - обман, хотя ответов нет. Следует ли перенести ответ о keys() из моего вопроса или вы говорите, что он неправильный, и хотя ответы здесь выглядят устаревшими, один из них является правильным?   -  person hippietrail    schedule 26.04.2015
comment
@hippietrail: Я не понимаю, почему ответы здесь устарели. (Как) они не работают на вас? Кажется, это именно то, что вам нужно, если я правильно понял ваш вопрос.   -  person Bergi    schedule 26.04.2015


Ответы (5)


Вам нужно будет делать эту работу самостоятельно. Прочтите все свойства в первый раз, когда сможете. С этого момента вы можете сравнивать список свойств со своим статическим.

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;
    }
}

Итак, теперь мы могли бы пойти как

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

и позже

window.foobar = 42;

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

Конечно, предостережение заключается в том, что вы можете «заморозить» глобальный список свойств только в то время, когда ваш скрипт может вызвать его в самый ранний момент.

person jAndy    schedule 22.06.2013
comment
Думаю, это был бы наиболее точный ответ. - person andlrc; 22.06.2013
comment
Но, возможно, вам стоит упомянуть, что Object.getOwnPropertyNames является частью ECMAScript 5 Edition. Также filter и Array.indexOf - person andlrc; 22.06.2013
comment
@NULL ну, последние пару месяцев я упоминал об этом, чувствую, что пора двигаться дальше :) - person jAndy; 22.06.2013
comment
@jAndy определенно пора двигаться дальше, сейчас я поддерживаю только ie9 и выше, это отличный ответ, большое спасибо. - person GriffLab; 22.06.2013
comment
@jAndy, может быть, поместите readGlobalProps в IIFE таким образом, чтобы он вызывался, как только вы его определите? - person GriffLab; 22.06.2013
comment
@GriffLab Да. Я предполагаю, что точно так же, предполагая, что люди не беспокоятся о устаревших браузерах, я предполагаю, что они помещают свою логику приложения в закрытые частные области :-) - person jAndy; 22.06.2013
comment
keys(window) не заботится о большей части фильтрации? - person hippietrail; 26.04.2015
comment
Это не будет использовать пользовательский скрипт (Greasemonkey, Tapermonkey), поскольку я не верю, что пользовательский скрипт гарантированно запускается перед js на странице. Каким будет второй лучший метод в этом случае? - person hippietrail; 26.04.2015
comment
@hippietrail Раз уж вы не верите, ничего никогда не будет ...? Поверьте, есть еще что-то, Greasemonkey _ 1_, например. - person yckart; 28.05.2017

Вы также можете сравнить окно с чистой версией окна вместо того, чтобы пытаться сделать снимок во время выполнения для сравнения. Я запустил это в консоли, но вы можете превратить его в функцию.

// 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);
}());
person jungy    schedule 22.06.2013
comment
Ого. Это именно то, что я ожидал получить от ответа на этот вопрос! Наконец-то я могу удобно ковыряться в чужом коде :) - person Moritz Friedrich; 24.05.2017
comment
Консоль Chrome не регистрирует results должным образом с ноября. 18, мне пришлось сделать results глобальным, а затем зарегистрировать его. Отличный код! - person Bigood; 08.11.2018

Это в том же духе, что и ответ @jungy, но мы можем сделать это в 3 строчки:

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

Сначала мы добавляем скрытый iframe; затем мы проверяем существующие переменные на соответствие стандартному JavaScript API в iframe; затем мы удаляем iframe.

Для удобства работы было бы полезно отсортировать результаты в алфавитном порядке, и это все еще возможно в версии из 3 строк:

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

И его можно запаковать в закладку:

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';
person Siltaar    schedule 02.03.2018
comment
Было бы полезно отсортировать результаты в хронологическом порядке, и это все еще возможно в трехстрочной версии: ... Вы не имеете в виду алфавитный порядок? (хронологический будет означать, основанный на времени, а не на алфавитном / лексическом порядке) - person Venryx; 04.06.2019
comment
Правда, исправлено. Спасибо. - person Siltaar; 05.06.2019

Я запустил это в консоли в инструменте ChromeDev, и он скопировал все, что пользователь определил правильно

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()));
person Raza    schedule 03.11.2019
comment
Если на вашей странице есть фреймы iframe и возникает следующая ошибка, попробуйте запустить Chrome с флагом --disable-web-security: заблокирован доступ фрейму с источником к фрейму с перекрестным источником. - person Trent; 28.08.2020

Может быть, это?:

for (var property in window)
{
    if (window.hasOwnProperty(property))
        console.log(property)
}
person LonelyWebCrawler    schedule 22.06.2013
comment
он также предоставит свойство, определяемое браузером - person bugwheels94; 22.06.2013