# 使用對象展開運算符(Object Spread Operator)
因為不直接修改 state 是 Redux 的核心理念之一, 所以你會發現自己總是在使用 [`Object.assign()`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) 創建對象拷貝, 而拷貝中會包含新創建或更新過的屬性值。在下面的 `todoApp` 示例中, `Object.assign()` 將會返回一個新的
`state` 對象, 而其中的 `visibilityFilter` 屬性被更新了:
```javascript
function todoApp(state = initialState, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return Object.assign({}, state, {
visibilityFilter: action.filter
})
default:
return state
}
}
```
盡管這樣可行, 但 `Object.assign()` 冗長的寫法會迅速降低 reducer 的可讀性。
一個可行的替代方案是使用最近加入 JavaScript 規范的 [對象展開運算符](https://github.com/tc39/proposal-object-rest-spread)。對象展開運算符讓你可以通過展開運算符 (`...`) , 以更加簡潔的形式將一個對象的可枚舉屬性拷貝至另一個對象。對象展開運算符在概念上與 ES6 的 [數組展開運算符](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator) 相似。 我們試著用這種方式簡化 `todoApp` :
```javascript
function todoApp(state = initialState, action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return { ...state, visibilityFilter: action.filter }
default:
return state
}
}
```
當你在組合復雜對象時, 使用對象展開運算符帶來的好處將更加突出。例如下面的 `getAddedIds` 將一個 `id` 數組轉換為一個對象數組, 而這些對象的內容是由 `getProduct` 和 `getQuantity` 的結果組合而成。
```javascript
return getAddedIds(state.cart).map(id =>
Object.assign({}, getProduct(state.products, id), {
quantity: getQuantity(state.cart, id)
})
)
```
運用對象擴展運算符簡化上面的 `map` 調用:
```javascript
return getAddedIds(state.cart).map(id => ({
...getProduct(state.products, id),
quantity: getQuantity(state.cart, id)
}))
```
雖然對象展開運算符提案已經處于 ECMAScript [Stage 4](https://github.com/tc39/proposal-object-rest-spread#status-of-this-proposal) 提案階段,并且在 2018 規范版本中被接受。 但你仍然需要轉換編譯器才能將對象展開運算符應用在生產環境中, 如 [Babel](http://babeljs.io/)。 你可以使用 [`env`](https://github.com/babel/babel/tree/master/packages/babel-preset-env) 預設值, 安裝 [`babel-plugin-transform-object-rest-spread`](http://babeljs.io/docs/plugins/transform-object-rest-spread/) 并將其單獨添加到位于 `.babelrc` 的 `plugins` 數組中。
```json
{
"presets": ["@babel/preset-env"],
"plugins": ["transform-object-rest-spread"]
}
```
- 自述
- 介紹
- 動機
- 核心概念
- 三大原則
- 先前技術
- 學習資源
- 生態系統
- 示例
- 基礎
- Action
- Reducer
- Store
- 數據流
- 搭配 React
- 示例:Todo List
- 高級
- 異步 Action
- 異步數據流
- Middleware
- 搭配 React Router
- 示例:Reddit API
- 下一步
- 技巧
- 配置 Store
- 遷移到 Redux
- 使用對象展開運算符
- 減少樣板代碼
- 服務端渲染
- 編寫測試
- 計算衍生數據
- 實現撤銷重做
- 子應用隔離
- 組織 Reducer
- Reducer 基礎概念
- Reducer 基礎結構
- Reducer 邏輯拆分
- Reducer 重構示例
- combineReducers 用法
- combineReducers 進階
- State 范式化
- 管理范式化數據
- Reducer 邏輯復用
- 不可變更新模式
- 初始化 State
- 結合 Immutable.JS 使用 Redux
- 常見問題
- 綜合
- Reducer
- 組織 State
- 創建 Store
- Action
- 不可變數據
- 代碼結構
- 性能
- 設計哲學
- React Redux
- 其它
- 排錯
- 詞匯表
- API 文檔
- createStore
- Store
- combineReducers
- applyMiddleware
- bindActionCreators
- compose
- react-redux 文檔
- API
- 排錯