使用字符串键访问或创建嵌套JavaScript对象而不使用eval

使用字符串键访问或创建嵌套JavaScript对象而不使用eval,javascript,json,nested,eval,Javascript,Json,Nested,Eval,我正在寻找一个很好的解决方案,通过字符串值访问属性,但是如果属性不存在,它应该创建它。如果根结构已经定义了结构的某些部分,则不应覆盖属性,而应合并属性 例如,如果您有一个空对象test,并且您想在不使用eval的情况下设置一个深层结构。e、 g test = {} test.foo.name = "Hallo" // <<- foo is an Object test.foo[3] = "Test" // <<- foo should remain as Object,

我正在寻找一个很好的解决方案,通过字符串值访问属性,但是如果属性不存在,它应该创建它。如果根结构已经定义了结构的某些部分,则不应覆盖属性,而应合并属性

例如,如果您有一个空对象
test
,并且您想在不使用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

然而,有没有更好的方法来实现这一点?

在这种情况下,我不会重新发明轮子,而是使用。特别是功能。根据他们的例子:

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// => 4

_.set(object, ['x', '0', 'y', 'z'], 5);
console.log(object.x[0].y.z);
// => 5

您可以分割路径并通过遍历给定对象来减少路径。如果不存在对象,请使用名称或数组创建新属性。稍后指定值

函数设置值(对象、路径、值){
var way=path.replace(/\[/g',')。replace(/\]/g',)。split('.'),
last=way.pop();
减少(函数(o,k,i,kk){
返回o[k]=o[k]| |(是有限的(kk中的i+1?kk[i+1]:last)?[]:{});
},object)[last]=值;
}
var检验={};
设置值(测试,“foo.name”、“foo先生”);
设置值(测试,“foo.data[0].bar”,100);
设置值(test,“and.other[2].deep”,20);

控制台日志(测试)此解决方案正在工作,尽管它没有回答问题。无论如何,我决定接受这个解决方案,因为在我的项目中包含lodash并不是很重。所以谢谢你的解决方案。Nina Scholz的解决方案正是我一直在寻找的。你的问题明确地说,
我正在寻找一个通过字符串值访问属性的很好的解决方案
&
但是,有没有更好的方法来实现这一点?
。我认为我已经准确地回答了你的问题,事实上这是正确的答案。使用lodash是解决您的问题的更好方法,因为它完全满足您的需要,不会导致您出现错误等。您的问题没有指定不使用已验证的库。很抱歉,我只能将一个解决方案标记为“已接受”。Ninas解决方案更符合我的要求,从可用性的角度来看,它和你的一样好,但它不需要添加一个完整的第三方库。我必须承认,我的问题不够清楚,我应该补充说,如果有一种优雅的方式来实现这一点,我更喜欢非第三方解决方案。然而,Ninas解决方案正好解决了我的问题,并且没有做更多的事情。这就是为什么我更喜欢给她荣誉。这正是我一直在寻找的!谢谢这个解决方案既美观又优雅。但是仍然缺少一点,数组将作为对象处理。如果运行解决方案,您将看到数组用作字符串键而不是整数键。因此,最后的结构是错误的:不是
“key”:[{},{},…]
而是
“key”:{“0”:{},“1”:{}…]
我为数组添加了想要的特性,但现在您得到了
“另一个”:[undefined,undefined,{“deep”:20}]
.Wow!当然你会有
未定义的
,因为它是一个数组。但这正是人们所期望的。非常感谢你,非常好,很好,很轻的解决方案。
var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// => 4

_.set(object, ['x', '0', 'y', 'z'], 5);
console.log(object.x[0].y.z);
// => 5