2

我有一个可变的 json 对象(可能有无限的子结构):

var myObject={
    s1:{
        s2:'2',
        s3:'3'
    },
    s4:'4',
    s5:{
        s6:undefined
    },
    s7:'7'
};

我想找到第一个未定义的成员并返回它的引用,以便能够随时修改它(通过事件触发函数)

function findFirstUndefined(obj){
    for (var key in obj){
        if (typeof(obj[key]) === 'object'){
            var recursion=findFirstUndefined(obj[key])
            if (recursion!==false){
                return recursion;
            }       
        }
        else if (obj[key]===undefined){
            return obj[key];
        }   
    }
    return false; 
}

但它不返回成员的引用,但它的值:

var subObj=findFirstUndefined(myObject);
subObj="my updated cool var!!";

不修改对象。

我发现像JsonPath这样的库可以做到这一点,但在我看来,对于这样一个简单的任务来说有点繁重。

难道不存在一种优雅的方式吗?谢谢!

4

5 回答 5

5

JS 不这样做。您可以改为返回一个将分配给缺失条目的函数?

return function(v) { obj[key] = v; };
于 2012-11-21T23:24:19.433 回答
1

在 JS 中,您无法手动控制是否传递了值或引用。

并且只有对象通过引用传递。

所以不幸的是你不能这样做。

于 2012-11-21T23:23:55.060 回答
1

正如您在评论中要求的那样,我将发布一种基于字符串路径获取/设置这些对象的方法。当然,您是否认为它太复杂取决于您,但就是这样。

function getValue(object, path) {
    value = object[path[0]];
    if (path.length > 1) {
        return getValue(value, path.slice(1, path.length))
    }
    return value;
}

function setValue(object, path, value) {
    if (path.length > 1) {
        setValue(object[path[0]], path.slice(1, path.length), value);
    }
    else {
        object[path[0]] = value
    }
}

然后,您可以像这样使用它们:getValue(myObject, ["s1", "s2"]);/ setValue(myObject, ["s1", "s2"], value);。我还没有机会测试代码,但这种方法应该成立。

于 2012-11-24T16:23:06.010 回答
0

如果您返回obj[key],您显然会返回一个值,但尝试返回一个包含两个值的数组,[obj, key]并且您有一种引用该节点的方法。或者从您的递归函数中,您可以使用这些类型的对构建一个多维数组以供以后使用。

于 2012-11-21T23:25:37.733 回答
0
function findFirstUndefinedPath(obj){
    for (var key in obj){
        var path=[key];
        if (typeof(obj[key]) === 'object'){
            var subPath=findFirstUndefinedPath(obj[key]);
            if (subPath!==false){
                return path.concat(subPath);
            }       
        }
        else if (obj[key]===undefined){
            return path;
        }   
    }
    return false; 
}
于 2012-11-25T11:29:47.460 回答