正如你提到的,你可以在地方蔓延的使用Object.assign
:
{...state, x: 1}
應該給你同樣的結果
Object.assign({}, state, {x: 1})
注意空對象爲Object.assign
第一個參數。這樣做是將state
中的值複製到一個新的空對象中,然後將{first: 1}
中的值複製到新對象中。
例如:
var a = { x: 1, y: 2}
var b = {...a, y: 3 }
console.log(a); // { x: 1, y: 2 }
console.log(b); // { x: 1, y: 3 }
相當於
var c = { x: 1, y: 2 }
var d = Object.assign({}, a, { y: 3 });
console.log(c); // { x: 1, y: 2 }
console.log(d); // { x: 1, y: 3 }
最重要的部分是,無論a
和c
不變。 b
和d
對於y
具有新值。
對於嵌套對象,重複這個過程:
function updateVeryNestedField(state, action) {
return Object.assign({}, state, {
first : Object.assign({}, state.first, {
second : Object.assign({}, state.first.second, {
[action.someId] : Object.assign({},
state.first.second[action.someId],
{ fourth : action.someValue }
)
})
})
});
}
var oldState = { first: { second: { 'anId': { fourth: 3 } } } };
var newState = updateVeryNestedField(oldState, { someId: 'anId', someValue: 5 });
console.log(oldState.first.second.anId.fourth); // 3
console.log(newState.first.second.anId.fourth); // 5
然而,對於全ES2015支持,你也將無法use computed keys。所以相反,你應該在return語句之前構建一些對象。例如:
function updateVeryNestedField(state, action) {
// Create a temporary object to avoid use of computed keys
var updatedSecond = Object.assign({}, state.first.second);
updatedSecond[action.someId] = Object.assign({}, state.first.second[action.someId], {
fourth: action.someValue
});
return Object.assign({}, state, {
first : Object.assign({}, state.first, { second : updatedSecond })
});
}
var oldState = { first: { second: { 'anId': { fourth: 3 } } } };
var newState = updateVeryNestedField(oldState, { someId: 'anId', someValue: 5 });
console.log(oldState.first.second.anId.fourth); // 3
console.log(newState.first.second.anId.fourth); // 5
簡單完美 - 謝謝。 – skwny
這在es5中是否允許:'[action.someId]:...'?使用uglifier.js進行縮小時會引發錯誤,而其他人也會遇到此問題。然而,它在捆綁但不縮小時通過。 – skwny
@skwy不幸的計算鍵是ES2015的一部分。我已更新我的示例以說明如何通過引入臨時對象來避免使用計算密鑰。新示例使用索引將屬性添加到臨時對象。 – grovesNL