0

我注意到与这篇文章的以下相似之处: JavaScript 对象的动态深度设置

但是,上面的帖子是基于 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. 将其列表更新为新列表(新数组)

新数组是应替换 complex_array2 列表的数组列表。javascript 函数walk就是这样做的,遍历 javascript 对象直到满足路径条件,然后将值设置为传递给 walk 函数的任何值,但是新值不会保留。

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

感谢您的任何帮助。

卡尔..

4

3 回答 3

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/

于 2013-09-09T20:46:13.773 回答
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]指向的对象。

于 2013-09-09T20:51:40.457 回答
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接受路径和对象。

于 2013-09-09T20:36:31.527 回答