使用不带eval的字符串键访问或创建嵌套的JavaScript对象 [英] Accessing or creating nested JavaScript objects with string key without eval
问题描述
我正在寻找一个通过字符串值访问属性的好方法,但如果该属性不存在,则应该创建它。如果根结构已经定义了结构的某些部分,则不应该覆盖属性,而是合并。
I am looking for a nice solution to access a property by string value, but if the property does not exist it should create it. If the root structure already has defined some parts of the structure, the attributes should not be overwritten, but merged instead.
例如,如果你有一个空对象 test
并且您想要在不使用eval的情况下设置深层结构。例如
For example if you have an empty object test
and you want to set a deep structure without using eval. e.g.
test = {}
test.foo.name = "Hallo" // <<- foo is an Object
test.foo[3] = "Test" // <<- foo should remain as Object, not as Array
test.foo.data[3].bar = 100 // <<- should not overwrite test.foo.name
我写了一个实际的解决方案我认为这是非常糟糕的代码:
I have written a solution that actually works, but it is quite bad code, I guess:
也可以作为jsfiddle使用: https://jsfiddle.net/gvaLzqqf/4/
Also available as jsfiddle: https://jsfiddle.net/gvaLzqqf/4/
Object.setValue = function(node, flatKey, value) {
flatKey = flatKey.replace("[", ".");
flatKey = flatKey.replace("]", "");
var parts = flatKey.split(".")
var oldNode = node
parts.forEach(function(key, index) {
if (/^\+?(0|[1-9]\d*)$/.test(key)) {
key = key * 1
if (index > 0) {
var oldValue = parts[index - 1]
if (!Array.isArray(oldNode[oldValue])) {
oldNode[oldValue] = []
node = oldNode[oldValue]
}
}
}
if (node[key] == undefined) {
node[key] = {}
}
oldNode = node
node = node[key]
}); // for each
oldNode[parts[parts.length - 1]] = value
return oldNode[parts[parts.length - 1]]
} // function
var test = {}
Object.setValue(test, "foo.name", "Mr. Foo")
Object.setValue(test, "foo.data[0].bar", 100)
Object.setValue(test, "and.another[2].deep", 20)
console.log("test = " + JSON.stringify(test))
console.log("test.foo.data[0].bar = " + test.foo.data[0].bar)
但是,有没有更好的方法来实现这一目标?
How ever, is there any better way to achieve this?
推荐答案
你可以通过遍历给定对象来分割路径并减少路径。如果不存在Object,请使用名称或数组创建新属性。稍后分配值。
You could split the path and reduce the path by walking the given object. If no Object exist, create a new property with the name, or an array. Later assign the value.
function setValue(object, path, value) {
var way = path.replace(/\[/g, '.').replace(/\]/g, '').split('.'),
last = way.pop();
way.reduce(function (o, k, i, kk) {
return o[k] = o[k] || (isFinite(i + 1 in kk ? kk[i + 1] : last) ? [] : {});
}, object)[last] = value;
}
var test = {};
setValue(test, "foo.name", "Mr. Foo");
setValue(test, "foo.data[0].bar", 100);
setValue(test, "and.another[2].deep", 20);
console.log(test);
这篇关于使用不带eval的字符串键访问或创建嵌套的JavaScript对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!