JavaScript迭代对象属性 - 陷入循环引用循环

时间:2016-10-18 15:14:05

标签: javascript loops

我有一个大对象(它有大约200个属性),我想像这样打印它:

[property1: alice, property2: bob, property3: 42, ...]

如果属性是一个函数,我希望它打印函数的代码,如果它是一个数组,我希望它打印该数组的每个元素。此外,如果属性是对象,它还应该打印它的属性等等......

我试图以递归方式实现这一点,但当然调用堆栈的速度非常快。然后我转向使用堆栈的迭代实现。这就是我所拥有的:

function getPropertyString(obj) {
    var res = "";
    var stack = [];
    stack.push(obj);
    while(stack.length > 0){
        var object = stack.pop();
        res += "[";
        for(var prop in object) {
            if(prop == null) continue;
            if(typeof object[prop] === 'object') {
                stack.push(object[prop]);
            } else {
                res += prop + ": " + 
                       object[prop].toString().replace(/[\t\r\n]/g, "") + ", ";
            }
        }
        res += "],";
    }
    return res;
}

如果您有像

这样的对象,这可以正常工作
var a = {
    b : {
        c : "hello",
        d : "world"
    },
    e : "alice",
    f : "bob",
    g : function() {
        console.log("hello");
    },
    h : [1, 2, 3]
}

但请假设您修改a以便a.x = {}; a.x.prototype = a;。然后我的函数会陷入无限循环。

我怎么能绕过这个?

2 个答案:

答案 0 :(得分:1)

如果首先JSON.stringify并将函数作为第二个参数传递(所谓的'replacer'),以便将方法转换为字符串,因为默认情况下JSON.stringify会丢弃函数。通过这种方式,您将获得所有属性,如果您设置了“无限循环”,那么JSON将提醒您。

答案 1 :(得分:1)

创建一个已从中处理过的对象数组 堆栈,不要再处理它们:(我标记了我添加的行来执行此操作)

function getPropertyString(obj) {
    var res = "";
    var stack = [];
    var objectHistory = []; // added this
    stack.push(obj);
    while(stack.length > 0){
        var object = stack.pop();
        if (objectHistory.indexOf(object) != -1) continue;  // added this
        objectHistory.push(object);  // added this
        res += "[";
        for(var prop in object) {
            if(prop == null) continue;
            if(typeof object[prop] === 'object') {
                stack.push(object[prop]);
            } else {
                res += prop + ": " +
                       object[prop].toString().replace(/[\t\r\n]/g, "") + ", ";
            }
        }
        res += "],";
    }
    return res;
}

var a = {
    b : {
        c : "hello",
        d : "world"
    },
    e : "alice",
    f : "bob",
    g : function() {
        console.log("hello");
    },
    h : [1, 2, 3]
};

a.x = {
  i: "I am X"
};
a.x.prototype = a;

console.log(getPropertyString(a));