w3schools tag tab style page for color javascript string properties nested

tag - Cómo establecer la propiedad del objeto(de la propiedad del objeto de...) dado su nombre de cadena en JavaScript?



title of page html (10)

Supongamos que solo nos dan

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

¿Cómo podemos establecer la propiedad obj.foo.bar.foobar a un cierto valor (por ejemplo, "hello world")? Así que quiero lograr esto, mientras que solo tenemos el nombre de la propiedad en una cadena:

obj.foo.bar.foobar = "hello world";


Una muy simple.

Sin recurrencias ni devoluciones de llamadas por sobrecarga.

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


Aquí hay una función get y set que acabo de compilar a partir de un par de hilos + algún código personalizado.

También creará claves que no existen en el conjunto.

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


Aquí hay una función simple para hacer eso usando referencia.

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


Aquí hay uno que devuelve el objeto actualizado

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


Dado que esta pregunta parece responderse con respuestas incorrectas, solo me referiré a la respuesta correcta de una pregunta similar

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

Utilizar:

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


Puede dividir la ruta y verificar si el siguiente elemento existe. Si no asigna un objeto a la nueva propiedad.

Devuelve luego el valor de la propiedad.

Al final asigna el valor.

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


Sé que es antiguo, pero solo veo funciones personalizadas en las respuestas.
Si no te importa usar una biblioteca, mira lodash _.set y _.get function.


Todas las soluciones sobrepasaban cualquiera de los datos originales cuando se configuraba, así que modifiqué con lo siguiente, también lo convertí en un solo objeto:

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

También puede cambiar las funciones para que sean un método Oject.prototype cambiando obj param por esto:

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


editar: he creado un testcase jsPerf.com para comparar la respuesta aceptada con mi versión. Resulta que mi versión es más rápida, especialmente cuando vas muy profundo.

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

1.

1.


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