2011-12-07 2 views
3

짧은 버전 :자바 스크립트를 사용하여 (다른 DOM 나) 모든 개체를 가져옵니다

  • 가 어떻게 그냥 (페이지 ( 객체 자신의 후손을 포함하여) 모든 객체의 목록을하지 얻을 수 있습니다 첫 번째 깊이 개체)?
    • 예상 하위 문제 : 방문한 개체를 걸을 때 을 어떻게 추적 할 수 있습니까?

미리 감사드립니다.



(! 배경으로) 긴 버전 :

우리는 객체의 속성이 모두 얻을 수있는 in 키워드를 사용. 좋은 출발점이

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

(그리고 hasOwnProperty 방법을 사용하여. 우리가 상속 된 사람을 해당 객체에 속하고뿐만 아니라 속성을 필터링 할 수 있습니다)하지만 난 모든 개체를 좀하고 싶습니다. 모든 속성을 반복하고 객체를 누적 한 다음 재귀 적으로 반복하여 객체를 반복하는 것을 상상할 수 있습니다. 그러나 객체 참조 루프가있는 경우 객체 자체가 window.window과 같이 참조 된 것처럼 해당 객체에 갇히지 않는 것이 좋습니다. 따라서 재귀 중에 모든 '방문 객체'를 추적하는 방법이 필요합니다.

방문한 개체를 추적하려면 내부 개체 키를 기반으로 실제로 개체의 해시 집합이 필요합니다. 나는 visitedObjects 객체를 만들고 그 객체를 추가 할 객체로 키를 설정해 보았습니다. 값은 중요하지 않았습니다.

하지만 그건 저에게 도움이되지 못했습니다. (내부 참조 키를 사용하는 대신 개체를 키의 문자열로 바꾸는 것 같습니다.)

대신 배열을 사용하고 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; 
} 

그러나 그것은 작동하지 않았다 중 (결국 내가 객체가 null는 아니고에도 불구하고 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에서 저를 위해 일하고 있지 않았습니다. 크롬에서도 잘 작동합니다.

+0

는 "페이지에"정의합니다. DOM 요소를 의미합니까? 전체 개체 아래에 전체 개체 트리를 의미합니까? –

+1

또한, 당신은 그 모든 물건으로 무엇을하고 싶습니까? –

+0

@ imeVidas : 전역 개체 아래에 전체 개체 트리가 있다고 가정합니다. 주어진 객체 아래의 전체 객체 트리가 하위 문제로 원하는 것입니다. – user420667

답변

8

내 빠른 시도 :

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 
+0

그럴거야. 감사. 나는 forEach와 builtins를 더 많이 사용하기 시작해야한다. – user420667

+0

내가 찾고있는 것. 완전한. – Bangkokian

관련 문제