Come impostare la proprietà dell’object (della proprietà dell’object di ..) dato il suo nome stringa in JavaScript?

Supponiamo che ci vengano dati solo

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

Come possiamo impostare la proprietà obj.foo.bar.foobar su un determinato valore (ad esempio “ciao mondo”)? Quindi voglio ottenere questo, mentre abbiamo solo il nome della proprietà in una stringa:

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

Poiché a questa domanda sembra essere data una risposta da risposte errate, mi limiterò a fare riferimento alla risposta corretta da una domanda simile

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

Uso:

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

modifica: ho creato un testcase jsPerf.com per confrontare la risposta accettata con la mia versione. Risulta che la mia versione è più veloce, soprattutto quando si va molto in profondità.

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

Tutte le soluzioni sostituiscono tutti i dati originali durante l’impostazione, quindi ho apportato le seguenti modifiche, trasformandolo in un singolo object:

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

Può anche cambiare le funzioni in modo da essere un metodo Oject.prototype che cambia obj param in questo modo:

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

So che è vecchio, ma vedo solo le funzioni personalizzate nelle risposte.
Se non ti dispiace usare una libreria, guarda la funzione lodash _.set e _.get .

Ecco uno che restituisce l’object aggiornato

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

Ecco una semplice funzione per farlo usando il riferimento.

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

Uno molto semplice.

Nessuna ricorsione o callback 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); 

Ecco una funzione get e set che ho appena compilato da un paio di thread + qualche codice personalizzato.

Creerà anche chiavi che non esistono sul 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, '.$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; } 

È ansible dividere il percorso e verificare se il seguente elemento esiste. Se non si assegna un object alla nuova proprietà.

Ritorna quindi il valore della proprietà.

Alla fine assegna il valore.

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