Object.assign-override嵌套属性

时间:2017-01-11 10:15:29

标签: javascript ecmascript-6

我有一个像这样的对象a

const a = {
  user: {
   …
   groups: […]
   …
  }
}

a.user

中有更多属性

我想只更改a.user.groups值。如果我这样做:

const b = Object.assign({}, a, {
  user: {
    groups: {}
  }
});

b除了b.user.groups之外没有任何其他属性,所有其他属性都被删除。是否有任何ES6方法只能通过Object.assign更改嵌套属性而不会丢失所有其他属性?

8 个答案:

答案 0 :(得分:67)

经过一番尝试后,我找到了一个看起来非常漂亮的解决方案:

const b = Object.assign({}, a, {
  user: {
    ...a.user,
    groups: 'some changed value'
  }
});

为了使这个答案更加完整,请注意以下几点:

const b = Object.assign({}, a)

基本上与:

相同
const b = { ...a }

因为它只是将a...a)的所有属性复制到新对象。所以上面的内容可以写成:

 const b = {
   ...a,          //copy everything from a
   user: {        //override the user property
      ...a.user,  //same sane: copy the everything from a.user
      groups: 'some changes value'  //override a.user.group
   }
 }

答案 1 :(得分:6)

你可以这样改变,

var child = require('child_process');
var ps = child.spawn("gdb", ['gdb-test', '-q']);
ps.stdout.pipe(process.stdout);
ps.stdin.write('start');

或只是做,

//gdb-test.c:
#include<stdio.h>
int main()
{
    int i = 10;
    i++;
    printf("%d\n"); 
}

答案 2 :(得分:4)

  

Object.assign()方法用于将所有可枚举的自有属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

assign方法将通过从源对象复制来创建一个新对象,如果您稍后在源对象中更改任何方法,则该问题将不会反映到新对象中。

使用create()

  

Object.create()方法使用指定的原型对象和属性创建一个新对象。

const b = Object.create(a)
b.user.groups = {}
// if you don't want the prototype link add this
// b.prototype = Object.prototype 

通过这种方式,您可以通过原型链接到a,如果您对其进行任何更改,它将反映在b中,并且b中的任何更改都不会影响

答案 3 :(得分:3)

你专门询问了使用Object.assign的ES6方式,但也许其他人会更喜欢我更“通用”的答案 - 你可以用lodash轻松完成,而且我个人觉得这个解决方案更具可读性。

import * as _ from 'lodash';
_.set(a, 'user.groups', newGroupsValue);

它会改变对象。

答案 4 :(得分:1)

这是一个名为Object_assign的小函数(如果需要嵌套分配,只需将.替换为_

该函数通过直接粘贴源值或在目标值和源值均为非Object_assign对象时再次递归调用null来设置所有目标值。

const target = {
  a: { x: 0 },
  b: { y: { m: 0, n: 1      } },
  c: { z: { i: 0, j: 1      } },
  d: null
}

const source1 = {
  a: {},
  b: { y: {       n: 0      } },
  e: null
}

const source2 = {
  c: { z: {            k: 2 } },
  d: {}
}

function Object_assign (target, ...sources) {
  sources.forEach(source => {
    Object.keys(source).forEach(key => {
      const s_val = source[key]
      const t_val = target[key]
      target[key] = t_val && s_val && typeof t_val === 'object' && typeof s_val === 'object'
                  ? Object_assign(t_val, s_val)
                  : s_val
    })
  })
  return target
}

console.log(Object_assign(Object.create(target), source1, source2))

答案 5 :(得分:0)

小调的菲利普斯第一个答案。

const object1 = {
  abc: {
    a: 1
  }
};

const object2 = {
  abc: {
    b: 2
  }
};

Object.assign(object1, {
    abc: {
        ...object1.abc,
        ...object2.abc
    }
});

console.log(object1);
// Object { abc: Object { a: 1, b: 2 } }

答案 6 :(得分:0)

下面有更多常规解决方案。仅当存在冲突(键名相同)时,才进行递归分配。它解决了分配具有许多参考点的复杂对象的问题。 例如,nested-object-assign是npm中用于嵌套对象分配的现有程序包,因为它递归地遍历所有键,所以卡住了复杂的对象分配。

var objecttarget = {
  a: 'somestring',
  b: {x:2,y:{k:1,l:1},z:{j:3,l:4}},
  c: false
};

var objectsource = {
  a: 'somestring else',
  b: {k:1,x:2,y:{k:2,p:1},z:{}},
  c: true
};

function nestedassign(target, source) {
  Object.keys(source).forEach(sourcekey=>{
    if (Object.keys(source).find(targetkey=>targetkey===sourcekey) !== undefined && typeof source[sourcekey] === "object") {
      target[sourcekey]=nestedassign(target[sourcekey],source[sourcekey]);
    } else {
      target[sourcekey]=source[sourcekey];
    }
  });
  return target;
}

// It will lose objecttarget.b.y.l and objecttarget.b.z
console.log(Object.assign(Object.create(objecttarget),objectsource));

// Improved object assign
console.log(nestedassign(Object.create(objecttarget),objectsource));

答案 7 :(得分:0)

当嵌套对象时,我更喜欢使用这种小技巧。

const a = JSON.parse(JSON.stringify(b))