使用不带 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屋!