【问题标题】:Get all user defined window properties?获取所有用户定义的窗口属性?
【发布时间】:2025-12-29 05:10:06
【问题描述】:

有没有办法在javascript中找出所有用户定义的窗口属性和变量(全局变量)?

我试过console.log(window),但列表是无穷无尽的。

【问题讨论】:

  • @Bergi:这里的哪个答案涵盖了我刚刚被标记为这个问题的问题?你是说这个问题是骗人的,即使答案不是。关于keys() 的答案是否应该从我的问题中移出,或者你是说一个人错了,即使这里的答案看起来已经过时,其中一个是正确的答案??
  • @hippietrail:我不明白为什么这里的答案会过时。 (如何)他们不为你工作吗?如果我没有误解你的问题,这似乎正是你想要的。

标签: javascript browser properties window-object


【解决方案1】:

您还可以将窗口与干净版本的窗口进行比较,而不是在运行时尝试快照以进行比较。我在控制台中运行了它,但是你可以把它变成一个函数。

// 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);
}());

【讨论】:

  • Chrome 的控制台截至 11 月未正确记录 results。 18,我必须将 results 设为全局然后记录它。很棒的代码!
【解决方案2】:

您需要自己完成这项工作。尽可能第一时间阅读所有属性。从那时起,您可以将属性列表与静态列表进行比较。

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']

当然,这里需要注意的是,您只能在脚本能够最早调用全局属性列表时“冻结”全局属性列表。

【讨论】:

  • 我认为这将是最接近完美的答案。
  • 但也许你应该提到Object.getOwnPropertyNames 是 ECMAScript 5 版本的一部分。还过滤和 Array.indexOf
  • @NULL 好吧,过去几个月我已经习惯提到它了,我觉得是时候继续前进了:)
  • @jAndy 是时候继续前进了,我现在只支持 ie9 及以上版本,这是一个绝妙的答案,非常感谢。
  • @jAndy 可能将 readGlobalProps 放在 IIFE 中,这样一旦你定义它就会被调用?
【解决方案3】:

这与@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;然后我们针对 iframe 中的标准 JavaScript API 测试现有变量;然后我们删除 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';

【讨论】:

  • "按时间顺序对结果进行排序可能很有用,并且仍然可以在 3 行版本中:..." 你不是说按字母顺序吗? (按时间顺序表示基于时间,而不是按字母/词汇排序)
  • 正确,已修复。谢谢。
【解决方案4】:

我在 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()));

【讨论】:

  • 如果您的页面有 iframe 并引发以下错误,请尝试使用 --disable-web-security 标志启动 chrome:“阻止具有原点的框架”访问跨域框架。”
【解决方案5】:

窗口对象的属性是按时间顺序排列的。因此,在您的网页中包含的第一个脚本的开头创建一些具有唯一名称的变量并获取此属性的索引:

var abcdefghijklmnopqrstuvwxyz = true;
var firstOwnPropertyFound = Object.keys(window).indexOf('abcdefghijklmnopqrstuvwxyz');

然后在任何你想获取所有用户定义属性的数组的地方使用:

let myProp = Object.keys(window).slice(firstOwnPropertyFound);

或者如果你想跳过前两个变量:

let myProp = Object.keys(window).slice(firstOwnPropertyFound + 2);

myProp 变量是包含您创建的所有属性名称的数组。例如在我的测试网页中:

Array(7) [
  0: "abcdefghijklmnopqrstuvwxyz"
  1: "firstOwnPropertyFound"
  2: "st"
  3: "clog"
  4: "tstfnc"
  5: "tstFNC1"
  6: "obj"
  length: 7
]

然后访问所有变量:

myProp.forEach(item => {
  console.log(window[item]);
}

我使用它并且它有效。 (对不起我的英语不好)

【讨论】:

    【解决方案6】:

    也许是这个?:

    for (var property in window)
    {
        if (window.hasOwnProperty(property))
            console.log(property)
    }
    

    【讨论】:

    • 它也会给浏览器定义的属性