如何设置在JavaScript中的string名称的对象属性(的..的对象属性)?

假设我们只给予

var obj = {}; var propName = "foo.bar.foobar"; 

我们如何设置属性obj.foo.bar.foobar到一个特定的值(比如说“hello world”)? 所以我想实现这一点,而我们只有一个string的属性名称:

 obj.foo.bar.foobar = "hello world"; 
 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"); 

由于这个问题似乎是由不正确的答案回答,我只是从类似的问题提到正确的答案

 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; } } 

使用:

 var obj = {}; setDeepValue(obj, 'Hello World', 'foo.bar.foobar'); 

编辑:我创build了一个jsPerf.comtesting用例来比较接受的答案和我的版本。 事实certificate,我的版本更快,特别是当你深入的时候。

http://jsfiddle.net/9YMm8/

 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"); 

所有的解决scheme在设置时都包含了原始数据,所以我使用下面的方法进行了调整,并将其作为单个对象:

  var obj = {} nestObject.set(obj, "ab", "foo"); nestObject.get(obj, "ab"); // 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; } }; 

也可以改变函数是一个Oject.prototype方法改变obj参数为:

 Object.prototype = { setNested = function(){ ... }, getNested = function(){ ... } } {}.setNested('a.c','foo') 

我知道这是一个旧的,但我只看到自定义函数的答案。
如果您不介意使用库,请查看lodash _.set_.get函数。

这是一个返回更新的对象

 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'} } 

这里是一个get和set函数,我刚从一些线程+一些自定义代码编译。

它也会创build不存在的密钥。

 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, '.$1'); 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; } 

这是一个简单的函数来做到这一点使用参考。

  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; } 

您可以拆分path并检查是否存在以下元素。 如果不将对象分配给新的属性。

然后返回属性的值。

最后分配值。

 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); 

一个非常简单的。

没有recursion或callback开销。

 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);