Javascript:用ES6速记修改嵌套对象

时间:2019-01-02 10:22:03

标签: javascript ecmascript-6 ecmascript-7

考虑一个函数返回一个嵌套对象,而我想修改嵌套对象内的属性。

在下面的示例中,我多次调用该函数,或者需要将其存储在一个临时变量中。有没有一种方法可以在花括号内仅调用一次,并在同一对象内多次传播/修改。

const getObject = () => {
   return {
     a: {
      b: {
        c: 1,
        d: 2,
      }
     },
     e: 3
   }
}

var modifiedD = {
  ...getObject(),
  a: {
     b: {
      ...getObject().a.b,
      d: 4
     }
  }
}

console.log(modifiedD);

3 个答案:

答案 0 :(得分:4)

a之后声明...getObject()键时,它将替换整个值。它不会合并a之后的内部对象。

因此您可以照做,并多次致电getObject()


另一种解决方案可能是使用您自己合并对象的功能来处理它,例如:

function mergeObjects(obj1, obj2) {
  // We are going to copy the value of each obj2 key into obj1
  Object.keys(obj2).forEach((x) => {
    // If we have an object, we go deeper
    if (typeof obj2[x] === 'object') {
      if (obj1[x] === void 0) {
        obj1[x] = {};
      }

      mergeObjects(obj1[x], obj2[x]);
    } else {
      obj1[x] = obj2[x];
    }
  });
  
  return obj1;
}

const getObject = () => {
  return {
    a: {
      b: {
        c: 1,
        d: 2,
      }
    },
    e: 3
  }
}

const modifiedD = mergeObjects(getObject(), {
  a: {
    b: {
      d: 4,
    },
  },
});

console.log(modifiedD);

警告,我创建的功能使对象变了,但这可能不是最佳答案


或者只调用一次,然后像下面这样一个接一个地设置键:

const getObject = () => {
   return {
     a: {
      b: {
        c: 1,
        d: 2,
      }
     },
     e: 3
   }
}

const modifiedD = getObject();

modifiedD.a.b.d = 4;

console.log(modifiedD);

答案 1 :(得分:0)

在我之前的回答中,正如GrégoryNEUT指出的那样,您可能会有更大的复杂性。

如果是这样,您可以简单地创建两个对象,然后将它们合并。我发现function code snippet可以使用Object.assign

来做到这一点

示例:

const getObject = () => {
   return {
     a: {
      b: {
        c: 1,
        d: 2,
      }
     },
     e: 3
   }
}

var modifiedD = getObject();
var newD = {
  a: {
     b: {
       d: 4
     },
     y: 1
  },
  z: 20
}

/** TAKEN FROM https://gist.github.com/ahtcx/0cd94e62691f539160b32ecda18af3d6 **/
// Merge a `source` object to a `target` recursively
const merge = (target, source) => {
  // Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
  for (let key of Object.keys(source)) {
    if (source[key] instanceof Object) Object.assign(source[key], merge(target[key], source[key]))
  }

  // Join `target` and modified `source`
  Object.assign(target || {}, source)
  return target
}

modifiedD = merge(modifiedD, newD);

console.log(modifiedD);

答案 2 :(得分:-1)

您可以尝试以下操作:

getParentObj(path, obj) {
   return path.split('.').reduce((o,i)=>o[i], obj);
}

const parent = getParentObj('a.b', getObject());
parent[d] = 24;