Javascript:使用遍历从 JSON 对象获取引用

发布于 2024-09-17 10:28:44 字数 1033 浏览 1 评论 0原文

我需要从 JSON 对象获取引用,代码如下:

var Tree = {
    data: {
        0: {
            pk: 1,
        },
        1: {
            pk: 2,
        },
        2: {
            pk: 3,
            children: {
                0: {
                    pk: 11,
                },
                1: {
                    pk: 22,
                },
                2: {
                    pk: 33,
                },
            },
        },
    },

    traverse: function(data, pk) {
        for (i in data) {
            // console.log(data[i]);
            if(data[i].pk && data[i].pk == pk)
                return data[i];

            if (typeof(data[i].children) == 'object')
                this.traverse(data[i].children, pk);
        };
    },
}

遍历顶级项目时,代码运行得很好:

>>> Tree.traverse(Tree.data, 1);
Object {pk=1}

但是在获取子元素时就损坏了:

>>> Tree.traverse(Tree.data, 22);
undefined

当您取消注释 ' 时,我很奇怪为什么会出现这种行为// console.log(data[i]);'行您将看到对象已获取但未返回。

有什么想法吗?

I need to get a reference from JSON object, the code just following:

var Tree = {
    data: {
        0: {
            pk: 1,
        },
        1: {
            pk: 2,
        },
        2: {
            pk: 3,
            children: {
                0: {
                    pk: 11,
                },
                1: {
                    pk: 22,
                },
                2: {
                    pk: 33,
                },
            },
        },
    },

    traverse: function(data, pk) {
        for (i in data) {
            // console.log(data[i]);
            if(data[i].pk && data[i].pk == pk)
                return data[i];

            if (typeof(data[i].children) == 'object')
                this.traverse(data[i].children, pk);
        };
    },
}

The code works very well when traverse the top level items:

>>> Tree.traverse(Tree.data, 1);
Object {pk=1}

But broken when get the child element:

>>> Tree.traverse(Tree.data, 22);
undefined

I'm very strange why it's this behavior, when you uncomment the '// console.log(data[i]);' line you will see the object is got but didn't returned.

Any idea about it ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

与酒说心事 2024-09-24 10:28:44

您没有将 return 放在 this.traverse(data[i].children, pk); 之前。


编辑:

var Tree = {
    data: {
        0: {
            pk: 1,
        },
        1: {
            pk: 2,
        },
        2: {
            pk: 3,
            children: {
                0: {
                    pk: 11,
                },
                1: {
                    pk: 22,
                },
                2: {
                    pk: 33,
                },
            },
        },
    },

    traverse: function(data, pk) {
        for (var i in data) {
            // console.log(data[i]);
            if(data[i].pk && data[i].pk == pk)
                return data[i];

            if (typeof(data[i].children) == 'object') {
                var retVal = this.traverse(data[i].children, pk);
                if (typeof retVal!='undefined') {//here was the logical problem,there might be more than one
                                                 //object, we can't return the result of traversing first one.
                                                 //So we will check, if no return, we go on searching
                    return retVal;
                }
            }

        };
    },
};

alert(Tree.traverse(Tree.data, 1).pk);
alert(Tree.traverse(Tree.data, 22).pk);

在这里检查实时:http://jsfiddle.net/rq4LK/

You didn't put return before this.traverse(data[i].children, pk);.


EDIT:

var Tree = {
    data: {
        0: {
            pk: 1,
        },
        1: {
            pk: 2,
        },
        2: {
            pk: 3,
            children: {
                0: {
                    pk: 11,
                },
                1: {
                    pk: 22,
                },
                2: {
                    pk: 33,
                },
            },
        },
    },

    traverse: function(data, pk) {
        for (var i in data) {
            // console.log(data[i]);
            if(data[i].pk && data[i].pk == pk)
                return data[i];

            if (typeof(data[i].children) == 'object') {
                var retVal = this.traverse(data[i].children, pk);
                if (typeof retVal!='undefined') {//here was the logical problem,there might be more than one
                                                 //object, we can't return the result of traversing first one.
                                                 //So we will check, if no return, we go on searching
                    return retVal;
                }
            }

        };
    },
};

alert(Tree.traverse(Tree.data, 1).pk);
alert(Tree.traverse(Tree.data, 22).pk);

check live here: http://jsfiddle.net/rq4LK/

寂寞清仓 2024-09-24 10:28:44

这是一个不太可能的事情,但您正在 for 循环中创建一个全局变量。尝试使用 for(var i in data) 来代替,然后请报告。

如果这不是整个对象,并且您在父 Object 文本中有一个带有键的属性(如 3: ...),但 Object 文本中不存在该属性, code>children 子属性,它显然会返回 undefined,因为该键没有这样的属性。

编辑:根据您的评论,这也可能是函数作用域的问题,因为您使用尾递归来迭代具有多层的对象。
因此,尝试将当前对象引用置于函数作用域之外,就像在任何需要动态引用的 javascript 语言构造中所做的那样:

var current = null , match = null ;

function traverse() {

    var data = arguments[0] ;
    var pk = arguments[1] ;

        for(var i in data) {

                current = data[i] ; /* DEBUG */console.log( current.toSource() ) ; //!! Object.prototype.toSource() requires a W3 compatible browser (like FF)

                if(current.pk !== undefined && current.pk === pk) return current ;
                else if( typeof current.children === "object") traverse(current.children, pk);

         }
}

match = traverse(data,pk) ;

编辑 2: 我的逻辑有缺陷。请尝试这样做:

var match = null ;

function traverse() {

    var data = arguments[0] ;
    var pk = arguments[1] ;

    var current = null ;

        for(var i in data) {

                current = data[i] ; /* DEBUG */console.log( current.toSource() ) ; //!! Object.prototype.toSource() requires a W3 compatible browser (like FF)

                if(current.pk !== undefined && current.pk === pk) match = current ; //!! if there is a match set the variable match to the current object
                else if( typeof current.children === "object") traverse(current.children, pk); //!! else use recursion to test a child property if present

         }

}

使用该方法,如果您的对象包含指定的属性,match 将不会为 null 并且将包含匹配的对象或子对象。

This is a long shot, but you are creating a global variable in your for loop. Try for(var i in data) instead and then report back please.

In case this is not the whole object and you have a property with a key (like 3: ...) in the parent Object literal that does not exist in the children child property, it will obviously return undefined, as there is no such property by that key.

Edit: As per your comment, this might also be a problem with function scope as you are using tail recursion to iterate over an object with multiple layers.
Thus, try to put the current object reference outside the function scope as you would do in any javascript language construct that requires a dynamic reference:

var current = null , match = null ;

function traverse() {

    var data = arguments[0] ;
    var pk = arguments[1] ;

        for(var i in data) {

                current = data[i] ; /* DEBUG */console.log( current.toSource() ) ; //!! Object.prototype.toSource() requires a W3 compatible browser (like FF)

                if(current.pk !== undefined && current.pk === pk) return current ;
                else if( typeof current.children === "object") traverse(current.children, pk);

         }
}

match = traverse(data,pk) ;

Edit 2: Flawed logic on my part. Try this instead:

var match = null ;

function traverse() {

    var data = arguments[0] ;
    var pk = arguments[1] ;

    var current = null ;

        for(var i in data) {

                current = data[i] ; /* DEBUG */console.log( current.toSource() ) ; //!! Object.prototype.toSource() requires a W3 compatible browser (like FF)

                if(current.pk !== undefined && current.pk === pk) match = current ; //!! if there is a match set the variable match to the current object
                else if( typeof current.children === "object") traverse(current.children, pk); //!! else use recursion to test a child property if present

         }

}

Using that, if your object contains the specified property match won't be null and will contain the matching object or child object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文