如何在 JavaScript 中给定字符串名称的对象属性(...的对象属性)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13719593/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set object property (of object property of..) given its string name in JavaScript?
提问by Chiel ten Brinke
Suppose we are only given
假设我们只得到
var obj = {};
var propName = "foo.bar.foobar";
How can we set the property obj.foo.bar.foobarto a certain value (say "hello world")?
So I want to achieve this, while we only have the property name in a string:
我们如何将属性obj.foo.bar.foobar设置为某个值(比如“hello world”)?所以我想实现这一点,而我们只有一个字符串中的属性名称:
obj.foo.bar.foobar = "hello world";
回答by VisioN
function assign(obj, prop, value) {
if (typeof prop === "string")
prop = prop.split(".");
if (prop.length > 1) {
var e = prop.shift();
assign(obj[e] =
Object.prototype.toString.call(obj[e]) === "[object Object]"
? obj[e]
: {},
prop,
value);
} else
obj[prop[0]] = value;
}
var obj = {},
propName = "foo.bar.foobar";
assign(obj, propName, "Value");
回答by Cerbrus
Since this question appears to be answered by incorrect answers, I'll just refer to the correct answer from a similar question
由于这个问题似乎是由不正确的答案回答的,我将参考类似问题中的正确答案
function setDeepValue(obj, value, path) {
if (typeof path === "string") {
var path = path.split('.');
}
if(path.length > 1){
var p=path.shift();
if(obj[p]==null || typeof obj[p]!== 'object'){
obj[p] = {};
}
setDeepValue(obj[p], value, path);
}else{
obj[path[0]] = value;
}
}
Use:
用:
var obj = {};
setDeepValue(obj, 'Hello World', 'foo.bar.foobar');
回答by Stephan B?nnemann-Walenta
edit: I've created a jsPerf.com testcaseto compare the accepted answer with my version. Turns out that my version is faster, especially when you go very deep.
编辑:我创建了一个jsPerf.com 测试用例来将接受的答案与我的版本进行比较。事实证明,我的版本更快,尤其是当你深入时。
var nestedObjectAssignmentFor = function(obj, propString, value) {
var propNames = propString.split('.'),
propLength = propNames.length-1,
tmpObj = obj;
for (var i = 0; i <= propLength ; i++) {
tmpObj = tmpObj[propNames[i]] = i !== propLength ? {} : value;
}
return obj;
}
var obj = nestedObjectAssignment({},"foo.bar.foobar","hello world");
?
?
?
?
回答by Micha? Fr?czkiewicz
回答by Labithiotis
All solutions overid any of the original data when setting so I have tweaked with the following, made it into a single object too:
所有解决方案在设置时都覆盖了任何原始数据,因此我对以下内容进行了调整,使其也成为单个对象:
var obj = {}
nestObject.set(obj, "a.b", "foo");
nestObject.get(obj, "a.b"); // returns foo
var nestedObject = {
set: function(obj, propString, value) {
var propNames = propString.split('.'),
propLength = propNames.length-1,
tmpObj = obj;
for (var i = 0; i <= propLength ; i++) {
if (i === propLength){
if(tmpObj[propNames[i]]){
tmpObj[propNames[i]] = value;
}else{
tmpObj[propNames[i]] = value;
}
}else{
if(tmpObj[propNames[i]]){
tmpObj = tmpObj[propNames[i]];
}else{
tmpObj = tmpObj[propNames[i]] = {};
}
}
}
return obj;
},
get: function(obj, propString){
var propNames = propString.split('.'),
propLength = propNames.length-1,
tmpObj = obj;
for (var i = 0; i <= propLength ; i++) {
if(tmpObj[propNames[i]]){
tmpObj = tmpObj[propNames[i]];
}else{
break;
}
}
return tmpObj;
}
};
Can also change functions to be an Oject.prototype method changing obj param to this:
也可以将函数更改为 Oject.prototype 方法,将 obj 参数更改为:
Object.prototype = { setNested = function(){ ... }, getNested = function(){ ... } }
{}.setNested('a.c','foo')
回答by Daniel Lizik
Here's one that returns the updated object
这是一个返回更新后的对象
function deepUpdate(value, path, tree, branch = tree) {
const last = path.length === 1;
branch[path[0]] = last ? value : branch[path[0]];
return last ? tree : deepUpdate(value, path.slice(1), tree, branch[path[0]]);
}
const path = 'cat.dog';
const updated = deepUpdate('a', path.split('.'), {cat: {dog: null}})
// => { cat: {dog: 'a'} }
回答by Thiago Kroger
Here is a simple function to do that using reference.
这是一个简单的函数,可以使用引用来做到这一点。
function setValueByPath (obj, path, value) {
var ref = obj;
path.split('.').forEach(function (key, index, arr) {
ref = ref[key] = index === arr.length - 1 ? value : {};
});
return obj;
}
回答by Nina Scholz
You could split the path and make a check if the following element exist. If not assign an object to the new property.
您可以拆分路径并检查以下元素是否存在。如果没有将对象分配给新属性。
Return then the value of the property.
然后返回该属性的值。
At the end assign the value.
最后赋值。
function setValue(object, path, value) {
var fullPath = path.split('.'),
way = fullPath.slice(),
last = way.pop();
way.reduce(function (r, a) {
return r[a] = r[a] || {};
}, object)[last] = value;
}
var object = {},
propName = 'foo.bar.foobar',
value = 'hello world';
setValue(object, propName, value);
console.log(object);
回答by Vitim.us
A very straightforward one.
很直接的一个。
No recursions or callbacks overhead.
没有递归或回调开销。
function setDeepVal(obj, path, val) {
var props = path.split('.');
for (var i = 0, n = props.length - 1; i < n; ++i) {
obj = obj[props[i]] = obj[props[i]] || {};
}
obj[props[i]] = val;
return obj;
}
// TEST
var obj = { hello : 'world' };
setDeepVal(obj, 'foo.bar.baz', 1);
setDeepVal(obj, 'foo.bar2.baz2', 2);
console.log(obj);
回答by Dieter Gribnitz
Here is a get and set function i just compiled from a couple of threads + some custom code.
这是我刚刚从几个线程 + 一些自定义代码编译的 get 和 set 函数。
It will also create keys that don't exist on set.
它还将创建现场不存在的密钥。
function setValue(object, path, value) {
var a = path.split('.');
var o = object;
for (var i = 0; i < a.length - 1; i++) {
var n = a[i];
if (n in o) {
o = o[n];
} else {
o[n] = {};
o = o[n];
}
}
o[a[a.length - 1]] = value;
}
function getValue(object, path) {
var o = object;
path = path.replace(/\[(\w+)\]/g, '.');
path = path.replace(/^\./, '');
var a = path.split('.');
while (a.length) {
var n = a.shift();
if (n in o) {
o = o[n];
} else {
return;
}
}
return o;
}

