Javascript窗口树递归和无限对象

标签 javascript recursion infinite-loop

我正在尝试编写一个函数,为所有浏览器转储window的递归树。我立即意识到我将遇到的一个问题与无限对象(window.window.window.window)有关。只是为了搞笑,我还是尝试了一下,正如我所料,我得到了一个错误。 未捕获的 RangeError:超出最大调用堆栈大小(在 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窗口树递归和无限对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9426181/

相关文章:

recursion - F# 递归对象

c - '\0' != 0 不是真的吗?

c - scanf 忽略,无限循环

javascript - React应用程序,componentDidUpdate - 跳跃列表,无限循环

Javascript 正则表达式替换可能包含重音字符的单词

javascript - 简化控制 3 个单独下拉菜单的 JavaScript 点击计数菜单

javascript - D3.JS SVG 矩形不出现

javascript - 选择特定下拉列表时添加一个类?

python - 为什么这个抛出错误的递归 Python 函数在最后几次调用中来回跳转?

recursion - 术语 'single pass' 是如何定义的?