当同时传递其他对象时,为什么Object.assign({},...)具有空的对象常量?

时间:2018-07-13 21:37:08

标签: javascript

我正在阅读Redux减速器(https://redux.js.org/introduction/three-principles)的介绍,其中包含以下减速器示例:

function todos(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [
        ...state,
        {
          text: action.text,
          completed: false
        }
      ]
    case 'COMPLETE_TODO':
      return state.map((todo, index) => {
        if (index === action.index) {
          return Object.assign({}, todo, {
            completed: true
          })
        }
        return todo
      })
    default:
      return state
  }
}

从其文档(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)看来,Object.assign()将“合并”传递给它的所有对象。但是,在这种情况下,todo{completed: true}已经是对象,因此我看不到将空对象文字{}作为{{1的第一个参数}}。有人可以澄清吗?

3 个答案:

答案 0 :(得分:3)

使用Object.assign时,您给它的第一个对象将把所有其余对象合并到其中。也就是说,第一个对象将被突变。

如果要避免使要合并的对象发生变异,则将空对象作为第一个参数传入会有所帮助,以防止任何组件对象发生更改。

下面是一个展示差异的示例:

const obj1 = {
  foo: "bar"
}

const obj2 = {
  key: "value"
}

// Here, obj1 is the same after the Object.assign call
console.log(Object.assign({}, obj1, obj2));
console.log(obj1)
console.log(obj2)

console.log("\n\n")

// Note that after this call, obj1 holds both keys. So this will mutate it:
console.log(Object.assign(obj1, obj2));
console.log(obj1) // This is different now
console.log(obj2)

答案 1 :(得分:1)

如果您不传入空对象,则原始todo对象将被修改。这可能是您想要的,但通常不是。

这是由于对象都是引用的方式,默认情况下不会克隆。

答案 2 :(得分:1)

简短答案:对象和数组是通过引用分配的。

在此示例中,更改一个将更改另一个,但它们并非一成不变的:

let x = {param:1}

const foo = (a) => {
  a.param +=1;
  console.log('response', x, a)
}
foo(x);

要解决此问题,我们使用Object.assign()

let x = {param:1}

const foo = (a) => {
  let b = Object.assign({}, a);
  b.param +=1;
  console.log('response', b, x)
}
foo(x);