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

use*_*667 6 javascript javascript-objects

简短版本:

  • 如何在页面上获取所有对象(包括其后代对象)的列表(而不仅仅是第一个深度对象)?
    • 预期的子问题:当我走过物体时,如何跟踪被访问的对象?

提前致谢.



长版(带背景!!):

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

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

这是一个很好的起点,但我想得到所有的对象.可以想象迭代所有属性并累积对象,然后递归迭代这些属性.但是,如果有一个对象引用循环,就像一个自己引用的对象,比如in window.window,那么最好不要陷入困境.因此,需要一种方法来跟踪递归期间的所有"访问对象".

要跟踪被访问对象,需要根据内部对象键真正需要对象的哈希集.我尝试通过制作一个visitedObjects对象并将其设置为要添加的对象,并且值无关紧要.

if(visitedObjects[obj] == 1){return;}
visitedObjects[obj] = 1;
Run Code Online (Sandbox Code Playgroud)

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

所以我决定使用一个数组并添加一个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; 
}
Run Code Online (Sandbox Code Playgroud)

但这也没有用(最终我得到了我不能做的,for(var prop in obj)即使对象不是null!调试器说obj不支持该属性.)

在任何情况下,这是我的错误代码:

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); };
Run Code Online (Sandbox Code Playgroud)

更新 实际上,字典可能是更好的方法.它只是在IE中不适合我.虽然工作正常铬.

Šim*_*das 11

我的快速尝试:

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
Run Code Online (Sandbox Code Playgroud)