Краткая версия:
- Как получить список всех объектов (включая объекты-потомки) на странице (не только объекты первой глубины)?
- Ожидаемая подзадача : Как я могу отслеживать посещенные объекты во время прогулки по ним?
Заранее спасибо.
Длинная версия (с фоном !!):
Используя ключевое слово 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.хотя в хроме отлично работает.