使用 JavaScript 获取所有对象(DOM 或其他)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8409577/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 03:21:47  来源:igfitidea点击:

Get all the objects (DOM or otherwise) using JavaScript

javascriptjavascript-objects

提问by user420667

The short version:

简短版本:

  • How can I get a list of all the objects (including their descendant objects) on the page (not just the first-depth objects)?
    • Anticipated subproblem: How can I track the visited objects as I walk the objects?
  • 如何获取页面上所有对象(包括它们的后代对象)的列表(不仅仅是第一深度对象)?
    • 预期子问题:如何在行走对象时跟踪访问过的对象?

Thanks in advance.

提前致谢。





The long version (with background!!):

长版(有背景!!):

Using the inkeyword we can get all the properties of an object. (And using the hasOwnPropertymethod allows us to filter out only the properties that belong to that object and not the inherited ones.)

使用in关键字我们可以获得一个对象的所有属性。(并且使用该hasOwnProperty方法允许我们仅过滤掉属于该对象的属性,而不是继承的属性。)

for (var prop in obj) {
   if (typeof(obj[prop]) == 'object'  && obj.hasOwnProperty(prop)) {
            showObjectsOfInternal(obj[prop], visitedObjects); // recursion.
   }
}

That is a good starting point, but I would like to get all the objects. One could imagine iterating through all the properties and accumulating the objects, then recursively iterating through those. However, if there was an object reference loop, like an object referred to itself, such as in window.window, it would be good not to get trapped by that. So one needs a way to track all the 'visited objects' during the recursion.

这是一个很好的起点,但我想获得所有对象。可以想象遍历所有属性并累积对象,然后递归遍历这些对象。然而,如果有一个对象引用循环,比如一个对象引用自身,比如 in window.window,那么最好不要被它困住。因此,需要一种方法来在递归期间跟踪所有“访问过的对象”。

To track the visited object, one really needs a hashset of objects, based on their internal object key. I tried that by making a visitedObjectsobject and setting it's keys as the object to be added, and the value didn't matter.

为了跟踪访问过的对象,我们确实需要一个基于对象内部对象键的对象散列集。我通过创建一个visitedObjects对象并将其键设置为要添加的对象来尝试这样做,而值并不重要。

if(visitedObjects[obj] == 1){return;}
visitedObjects[obj] = 1;

But that didn't work for me. (It seems to turn the objects into strings for keys, instead of using their internal reference keys)

但这对我不起作用。(它似乎将对象转换为键的字符串,而不是使用它们的内部引用键)

So instead I decided to use an array and add an indexOfmethod.

所以我决定使用一个数组并添加一个indexOf方法。

Array.prototype.indexOf = function(obj){
   for(var i = 0; i < this.length; i++)
   {
      if(this[i] == obj) // reference comparison for non-primitive objects.
      {
         return i;
      }  
   }
   return -1; 
}

But that didn't work either (eventually I got that I couldn't do for(var prop in obj)even though the object wasn't null! The debugger said that obj did not support that property.)

但这也不起作用(最终我发现for(var prop in obj)即使对象不为空我也做不到!调试器说 obj 不支持该属性。)

In any case, here is my buggy code:

无论如何,这是我的错误代码:

function showObjectsOf(obj) {
    var objHolder = new Array();
    var ancestorNames = new Array();
    ancestorNames.push('obj');
    showObjectsOfInternal(obj, objHolder, ancestorNames);
}
function showObjectsOfInternal(obj, visitedObjects, ancestorNames) {
    if (visitedObjects.indexOf(obj) != -1) {
        return;
    }
    visitedObjects.push(obj);
    alert(getAncestorString(ancestorNames));
    for (var prop in obj) {
        if (typeof (obj[prop]) == 'object') {
            ancestorNames.push(prop);
            showObjectsOfInternal(obj[prop], visitedObjects, ancestorNames);
            ancestorNames.remove(prop);
        }
    }
}
function getAncestorString(ancestorNames) {
    return ancestorNames.join('.');
}

Array.prototype.indexOf = function(obj) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] == obj) {
            return i;
        }
    }
    return -1;
}
Array.prototype.remove = function(obj){
    var ind = this.indexOf(obj);
    if(ind != -1)
    {
        this.splice(ind,1);
    }
}
window.onload = function() { showObjectsOf(window); };

UpdateActually, the dictionary may be the better way to go. It just wasn't working for me in IE. works fine in chrome though.

更新实际上,字典可能是更好的方法。它只是在 IE 中对我不起作用。不过在 chrome 中工作正常。

回答by ?ime Vidas

My quick attempt:

我的快速尝试:

var objs = []; // we'll store the object references in this array

function walkTheObject( obj ) {
    var keys = Object.keys( obj ); // get all own property names of the object

    keys.forEach( function ( key ) {
        var value = obj[ key ]; // get property value

        // if the property value is an object...
        if ( value && typeof value === 'object' ) { 

            // if we don't have this reference...
            if ( objs.indexOf( value ) < 0 ) {
                objs.push( value ); // store the reference
                walkTheObject( value ); // traverse all its own properties
            } 

        }
    });
}

walkTheObject( this ); // start with the global object