简体   繁体   English

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

[英]Javascript: Get a reference from JSON object with traverse

I need to get a reference from JSON object, the code just following: 我需要从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);
        };
    },
}

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]);' 当您取消注释“ // console.log(data [i]);”时,为什么会出现这种行为我感到非常奇怪。 line you will see the object is got but didn't returned. 行,您将看到对象已获得但未返回。

Any idea about it ? 有什么想法吗?

You didn't put return before this.traverse(data[i].children, pk); 你没有把returnthis.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/ 在此处查看直播: http//jsfiddle.net/rq4LK/

This is a long shot, but you are creating a global variable in your for loop. 这是一个远景,但是您正在for循环中创建全局变量。 Try for(var i in data) instead and then report back please. 尝试for(var i in data)代替,然后报告。

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. 在这种情况下不整的对象和你的物业设有一个按键(如3: ... )在父Object并不在存在字面children子属性,它显然会返回undefined ,因为没有这样的该键的属性。

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: 因此,请像在需要动态引用的任何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) ;

Edit 2: Flawed logic on my part. 编辑2:我的逻辑有缺陷。 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. 使用该方法,如果您的对象包含指定的属性,则match不会为null ,而是包含匹配的对象或子对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM