56

与えられただけだとしましょう

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

obj.foo.bar.foobarプロパティを特定の値(「helloworld」など)に設定するにはどうすればよいですか?したがって、これを実現したいのですが、文字列にはプロパティ名しかありません。

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

15 に答える 15

88
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");
于 2012-12-05T09:21:36.877 に答える
12

この質問は誤答が多いようですので、類似質問の正解を参考にさせていただきます

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');
于 2012-12-05T09:21:15.793 に答える
5

編集:受け入れられた回答を自分のバージョンと比較するために、 jsPerf.comテストケースを作成しました。特にあなたが非常に深く行くとき、私のバージョンはより速いことがわかります。

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

</ p>

</ p>

于 2012-12-05T09:30:18.573 に答える
3

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'} }
于 2016-07-22T15:28:55.977 に答える
3

これは、参照を使用してそれを行う簡単な関数です。

    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;
    }
于 2016-10-19T15:32:29.077 に答える
3

非常に簡単なものです。

この実装は非常にパフォーマンスが高いはずです。シンプルさを維持しながら、再帰と関数呼び出しを回避します。

/**
 * Set the value of a deep property, creating new objects as necessary.
 * @param {Object} obj The object to set the value on.
 * @param {String|String[]} path The property to set.
 * @param {*} value The value to set.
 * @return {Object} The object at the end of the path.
 * @author github.com/victornpb
 * @see https://stackoverflow.com/a/46060952/938822
 * @example
 * setDeep(obj, 'foo.bar.baz', 'quux');
 */
function setDeep(obj, path, value) {
    const props = typeof path === 'string' ? path.split('.') : path;
    for (var i = 0, n = props.length - 1; i < n; ++i) {
        obj = obj[props[i]] = obj[props[i]] || {};
    }
    obj[props[i]] = value;
    return obj;
}
  
  

/*********************** EXAMPLE ***********************/

const obj = {
    hello : 'world',
};

setDeep(obj, 'root', true);
setDeep(obj, 'foo.bar.baz', 1);
setDeep(obj, ['foo','quux'], '');

console.log(obj);
// ⬇︎ Click "Run" below to see output

于 2017-09-05T18:07:44.597 に答える
1

既存の値を上書きせず、読みやすく、これを思いつくことができた答えを探していました。同じニーズを持つ他の人を助ける場合に備えて、これをここに残します

function setValueAtObjectPath(obj, pathString, newValue) {
  // create an array (pathComponents) of the period-separated path components from pathString
  var pathComponents = pathString.split('.');
  // create a object (tmpObj) that references the memory of obj
  var tmpObj = obj;

  for (var i = 0; i < pathComponents.length; i++) {
    // if not on the last path component, then set the tmpObj as the value at this pathComponent
    if (i !== pathComponents.length-1) {
      // set tmpObj[pathComponents[i]] equal to an object of it's own value
      tmpObj[pathComponents[i]] = {...tmpObj[pathComponents[i]]}
      // set tmpObj to reference tmpObj[pathComponents[i]]
      tmpObj = tmpObj[pathComponents[i]]
    // else (IS the last path component), then set the value at this pathComponent equal to newValue 
    } else {
      // set tmpObj[pathComponents[i]] equal to newValue
      tmpObj[pathComponents[i]] = newValue
    }
  }
  // return your object
  return obj
}
于 2018-10-19T08:29:02.683 に答える