我正在尝试编写一个函数,它将为所有浏览器转储window
的递归树。我立刻意识到我将遇到的一个问题,与无限对象(window.window.window.window
)有关。只是为了笑,我还是尝试了,我得到了一个错误,正如我所料。 Uncaught RangeError: Maximum call stack size exceeded
(在Chrome中测试)
因此,第一种检查导致这种情况的对象的方法就是:
if (variable != 'window' && variable != 'top' && variable != 'self' && variable != 'frames')
我想也许这会奏效,而我只是错过了一对。这是一个很好的理论,但我仍然得到最大的堆栈错误。因此,我决定在Chrome控制台中键入window
,并手动查找所有[DOMWindow]
类型,以添加到此列表中。在这样做时,我注意到了Infinity: Infinity
值,这让我进入了下一个方法:
if (typeof namespace[variable]['Infinity'] === 'undefined')
我仍然遇到了最大的堆栈错误,所以我做了一些谷歌搜索,并了解了isFinite
,所以现在我有:(编辑:实际上我刚刚意识到isFinite
isn'我的想法是什么)
if (isFinite(tree[variable]))
错误最终消失,但这种方法的问题是window
中的所有对象都为此返回false,因此递归失败。我意识到某些方法可能甚至不是跨浏览器兼容的,但如果我能在同一时间内至少在一个浏览器中工作,那将会很好。
那么如何检查会导致无限循环的对象呢?
这是我的代码,仅供可能感兴趣的人使用:
(function () {
window.onload = function () {
window.onload = ''; // don't want to get our own code
console.log((function (namespace) {
tree = {};
for (var variable in namespace) {
/* gonna need these later
var variable_typeof = typeof namespace[variable],
variable_object_tostring = Object.prototype.toString(namespace[variable]);
*/
//if (variable != 'window' && variable != 'top' && variable != 'self' && variable != 'frames')
//if (typeof namespace[variable]['Infinity'] === 'undefined')
if (isFinite(tree[variable]))
tree[variable] = arguments.callee(namespace[variable]);
else tree[variable] = 'Infinity';
}
return tree;
})(window)); // Start from root
}
})();
更新
对于任何有兴趣的人来说,这是我最终提出的产品
GGG在他的帮助下值得一提。
function loop (namespace) {
if (namespace['__infinite_test']) return '[[recursion]]'; // It's infinite
namespace['__infinite_test'] = true; // Note that we've been through this object
var tree = {};
for (var variable in namespace) {
try { // For an issue in Chrome throwing an error
namespace[variable]['__tester'] = null;
delete namespace[variable]['__tester'];
}
catch (e) {
tree[variable] = namespace[variable];
continue;
}
if (namespace.propertyIsEnumerable(variable)) tree[variable] = loop(namespace[variable]);
else tree[variable] = namespace[variable];
}
return tree;
}
console.log(loop(window));
答案 0 :(得分:2)
防止问题无限递归的一种方法是跟踪已经访问过的所有对象的列表,如果遇到已经访问过的对象,则不会递归到其中。
当您遇到列表中没有的对象时,将其添加到列表中然后递归到列表中。