将值设置为复杂的Javascript对象

时间:2013-09-09 20:29:39

标签: javascript

我注意到这篇文章的以下相似之处: Dynamic deep setting for a JavaScript object

然而,上面的帖子是基于javascript对象的已知结构和深度而不是真正的动态。真正的动态表明你没有任何关于结构的先验知识,只是一条路径和一个替代它的价值。我在JSFiddle上创建了一个相当不错的用例:

http://jsfiddle.net/kstubs/nJrLp/1/

function Message(message) {
$('result').insert('<div>' + message + '</div>');
}

var obj = {
"array": [1, 2, 3],
"boolean": true,
"null": null,
"number": 123,
"object": {
    "a": "b",
    "c": "d",
    "e": "f",
    "complex_array1": [{
        "g": "h"
    }, {
        "bingo": "bongo"
    }, {
        "x": {
            "complex_array2": [{
                "h": "i"
            }, {
                "j": "k"
            }, {
                "bingo": "bongo"
            }, {
                "bango": "jango"
            }]
        }
    }]
},
"string": "Hello World"
};

var list = [{
"h": "i"
}, {
"j": "k"
}];

function walk(path,value) {
var a = path.split('.');
var context = obj;

for (i = 0; i < a.size(); i++) {
    context = context[a[i]];
}

}

用例:

  1. 查找complex_array2
  2. 将其列表更新为新列表(新数组)
  3. 新数组是数组列表,应该替换complex_array2的列表。 javascript函数 walk 就是这样,遍历javascript对象直到满足路径条件,然后将值设置为传递给walk函数的任何值,但新值不会粘。

    我知道它为什么不坚持,因为当你走过类型数组的对象时,你会丢失指向原始对象的指针。因此,挑战在于 javascript对象,而不是丢失原始对象的上下文。

    感谢您的帮助。

    卡尔..

3 个答案:

答案 0 :(得分:1)

只是遍历路径中除最后一个元素之外的所有元素。然后最后一个元素用于循环后的赋值。

var i = 0;

for (; i < a.size() - 1; i++) {
    context = context[a[i]];
}

context[a[i]] = value;

从技术上讲,您可以将i的声明留在for内。我发现这个更清楚。

http://jsfiddle.net/nJrLp/2/

答案 1 :(得分:1)

你的代码无法正常工作的原因是因为你实际上在改变你的局部变量所指向的对象,而不是更改你所引用的对象的属性。

context = context[a[i]];

context是指向对象的指针,它是一个局部变量。分配给它时,您将分配一个新的指针值,该值将丢失对前一个对象的引用。如果要替换它,则必须从其父对象中引用它。假设parent是一个这样的对象;一旦找到目标对象的密钥名称(假设您已将其放在变量key中),就可以覆盖现有值:

parent[key] = new_value;

这将取消引用parent,找到由key命名的属性,并将其值(指针)替换为new_value的内存地址。你目前的工作是这样的:

var context = parent[key];
context = new_value;

在这种情况下,您只需更改局部变量context的指针值,而不是parent[key]指向的对象。

答案 2 :(得分:0)

我使用辅助函数来读取复杂的json对象。 (http://jsfiddle.net/JBBAJ/

var object = {
    data: {
        users: [
            {
                firstName: "White"
            },
            {
                firstName: "Black"
            }
        ]
    }
}
var read = function(path, obj) {
    var path = path.split(".");
    var item = path.shift();
    if(item.indexOf("]") == item.length-1) {
        // array
        item = item.split("[");
        var arrayName = item.shift();
        var arrayIndex = parseInt(item.shift().replace("]", ""));
        var arr = obj[arrayName || ""];
        if(arr && arr[arrayIndex]) {
            return read(path.join("."), arr[arrayIndex]);
        } else {
            return null;
        }
    } else {
        // object
        if(obj[item]) {
            if(path.length === 0) {
                return obj[item];
            } else {
                return read(path.join("."), obj[item]);
            }
        } else {
            return null;
        }
    }

}
console.log(read("data.users[0].firstName", object)); // White
console.log(read("data.users[1].firstName", object)); // Black
console.log(read("data.test.users[0]", object)); // null

函数 read 接受路径和对象。