为什么 Redux 示例将空对象作为第一个 Object.assign() 参数传递?

Why do Redux examples pass empty object as first Object.assign() argument?

redux project的todoMVC例子中,处理todos的reducer有这些行:

export default function todos(state = initialState, action){
    ...
    case EDIT_TODO:
      return state.map(todo =>
        todo.id === action.id ?
          Object.assign({}, todo, { text: action.text }) :
          todo
      )
}

这部分代码处理更新特定待办事项。我的问题是,因为 state.map() 总是 return 一个新数组。那么,还需要做吗:

Object.assign({}, todo, { text: action.text})

可不可以:

Object.assign(todo, { text: action.text})

更新

我了解 Object.assign({}, blah...)Object.assign(obj, blah...) 之间的区别。让我改一下我的问题:

Redux 希望 reducers return 一个新状态而不是改变现有状态。我得到它。在我的示例中,我有一个对象数组。我想交换前两个元素的顺序。查看 jsbin example here.

  1. 因为 Array.map 总是 return 是一个 新数组 ,对 return 的引用ed 数组保证是一个新数组。检查。
  2. 但是,returned 数组中的元素并非全新。对前两个元素的引用是新的。但是,第三项不是。它与旧数组中的第三项相同。

所以我的问题是第三个元素,我应该使用:

Object.assign({}, third_element) 或简单地 return the third_elment

Redux 是否想要一个新数组,其中包含对其中每个对象的新引用(即使存储在这些新对象中的值与旧对象相同),或者只是一个新数组,其中只有更新的元素是新的?

这就是 Object.assign 工作原理的本质。它return将目标对象作为其操作的return值。所以,在第一个语法中:

Object.assign({}, todo, { text: action.text})

您正在创建一个具有 todo{ text: action.text} 可枚举属性的全新对象。

如果你这样做:

Object.assign(todo, { text: action.text})

那么 todo 本身就是目标对象,所以它会发生变异,这就是 return 从 Object.assign 编辑的内容。

第一种方法是通过创建全新对象的新数组使映射操作完全不可变。

这是一个说明我的意思的 jsbin。请注意,在第一个示例中,数组中的原始对象已更改,这意味着状态已发生变化。第二个,原始对象保持不变:

https://jsbin.com/boxeserave/edit?html,js,console

我想补充 sma 的精彩回答并解释 为什么 需要从 Object.assign 编辑新对象 return。

根据 redux 的工作方式,如果 reducer returns 与它在 state 参数中收到的引用相同,redux 将假定状态没有改变并且不会更新意见。为了告诉 redux 你正在改变状态,你必须 return 一个新的引用。这就是为什么你总是会看到一个新的空对象 {} 作为 reducers 中 Object.assign 的第一个参数。

来自 Dan Abramov(Redux 的创建者)的推文:

Common Redux misconception: you need to deeply clone the state. Reality: if something inside doesn’t change, keep its reference the same!

https://twitter.com/dan_abramov/status/688087202312491008