【问题标题】:Get all the objects (DOM or otherwise) using JavaScript使用 JavaScript 获取所有对象(DOM 或其他)
【发布时间】:2012-01-14 15:00:51
【问题描述】:

简短版:

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

提前致谢。



长版(带背景!!):

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

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

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

要跟踪访问过的对象,确实需要一个对象的哈希集,基于它们的内部对象键。我尝试通过创建一个visitedObjects 对象并将其键设置为要添加的对象,而值无关紧要。

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

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

所以我决定使用数组并添加一个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; 
}

但这也不起作用(最终我发现我无法做到for(var prop in obj),即使对象不为空!调试器说 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); };

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

【问题讨论】:

  • 定义“在页面上”。你是说 DOM 元素吗?你的意思是全局对象下的整个对象树吗?
  • 另外,您可能想对所有这些对象做什么?
  • @ŠimeVidas:我想我的意思是全局对象下的整个对象树。我想任何给定对象下的整个对象树都是我想要的子问题。
  • 为什么?为什么需要这种方法?你也在寻找console.dir(window)

标签: javascript javascript-objects


【解决方案1】:

我的快速尝试:

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

【讨论】:

  • 就可以了。谢谢。我得开始更多地使用 forEach 和 builtins。
  • 注意它不会枚举嵌套数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-12
  • 2019-01-02
  • 2011-04-15
  • 2011-05-22
相关资源
最近更新 更多