【问题标题】:Javascript window tree recursion and infinite objectsJavascript窗口树递归和无限对象
【发布时间】:2012-03-14 15:12:11
【问题描述】:

我正在尝试编写一个函数,该函数将为所有浏览器转储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 不是我想的那样是的)

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));

【问题讨论】:

    标签: javascript recursion infinite-loop


    【解决方案1】:

    在您的问题中防止无限递归的一种方法是跟踪您已经访问过的所有对象的列表,如果遇到您已经访问过的对象,您不会递归到它。

    当遇到不在列表中的对象时,将其添加到列表中,然后递归到列表中。

    【讨论】:

    • 我实际上也尝试过,但它导致列表不完整。我可能会诉诸于此,并找到一些方法来详细说明它。也许我可以创建一个单独的函数来运行更多级别,并仅添加缺少的元素。必须对此进行集思广益。
    • @andrewjackson - 我怀疑你的实现中存在缺陷。分享您尝试过的代码,我们可以对其发表评论。
    • 我已经废弃了,我得重写它。这实际上是我尝试的第一件事,甚至在我所谓的“第一种方法”之前。我现在会重写它,更新它,然后告诉你我有什么。
    • 其实你是对的。我应该坚持原来的计划,我有一个很好的想法来实现这个,我认为它会很好。如果有人感兴趣,我会在完成后发布代码。我想我只是希望有更简单的东西,但我不介意复杂性。
    猜你喜欢
    • 2015-09-12
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    • 2011-10-04
    • 2014-08-17
    • 1970-01-01
    相关资源
    最近更新 更多