不可移动地移除对象中的属性
我正在使用Redux。 在我的reducer中,我试图从像这样的对象中移除一个属性:
const state = { a: '1', b: '2', c: { x: '42', y: '43' }, }
我想要这样的东西,而不必改变原来的状态:
const newState = { a: '1', b: '2', c: { x: '42', }, }
我试过了:
let newState = Object.assign({}, state); delete newState.cy
但由于某些原因,它从两个州删除财产。
可以帮助我做到这一点?
我发现ES5的数组方法像filter
, map
和reduce
有用的,因为他们总是返回新的数组或对象。 在这种情况下,我会使用Object.keys
迭代对象, Array#reduce
将其重新转换为对象。
return Object.assign({}, state, { c: Object.keys(state.c).reduce((result, key) => { if (key !== 'y') { result[key] = state.c[key]; } return result; }, {}) });
你可以使用lodash库中的_.omit(object, [paths])
path可以嵌套,例如: _.omit(object, ['key1.key2.key3'])
这是因为您正在将state.c
的值复制到另一个对象。 而这个值是一个指向另一个JavaScript对象的指针。 所以,这两个指针都指向同一个对象。
尝试这个:
let newState = Object.assign({}, state); console.log(newState == state); // false console.log(newState.c == state.c); // true newState.c = Object.assign({}, state.c); console.log(newState.c == state.c); // now it is false delete newState.cy;
你也可以做一个对象的深层拷贝。 看到这个问题 ,你会发现什么是最适合你的。
这个怎么样:
function removeByKey (myObj, deleteKey) { return Object.keys(myObj) .filter(key => key !== deleteKey) .reduce((result, current) => { result[current] = myObj[current]; return result; }, {}); }
它过滤应该删除的密钥,然后从剩余的密钥和初始对象中构build一个新的对象。 这个想法是从泰勒麦吉尼斯真棒reactjs程序被盗。
JSBin
function dissoc(key, obj) { copy = Object.assign({}, obj) delete copy[key] return copy }
另外,如果要寻找一个函数式编程工具包,请看Ramda 。
Immutable.js很简单:
const newState = state.deleteIn(['c', 'y']);
deleteIn()的描述
你可以使用Immutability helper来取消一个属性,在你的情况下:
import update from 'immutability-helper'; const updatedState = update(state, { c: { $unset: ['y'] } });
如何使用解构赋值语法?
const original = { foo: 'bar', stack: 'overflow', }; // If the name of the property to remove is constant const { stack, ...withoutFirst } = original; console.log(withoutFirst); // Will be { "foo": "bar" } // If the name of the property to remove is from a variable const key = 'stack' const { [key]: value, ...withoutSecond } = original; console.log(withoutSecond); // Will be { "foo": "bar" } // To do a deep removal with property names from variables const deep = { foo: 'bar', c: { x: 1, y: 2 } }; const parentKey = 'c'; const childKey = 'y'; // Remove the 'c' element from original const { [parentKey]: parentValue, ...noChild } = deep; // Remove the 'y' from the 'c' element const { [childKey]: removedValue, ...childWithout } = parentValue; // Merge back together const withoutThird = { ...noChild, [parentKey]: childWithout }; console.log(withoutThird); // Will be { "foo": "bar", "c": { "x": 1 } }
我通常使用
Object.assign({}, existingState, {propToRemove: undefined})
我意识到这不是实际上删除财产,但几乎所有的目的1其function相当。 这个语法比我认为是一个很好的折衷scheme要简单得多。
1如果您正在使用hasOwnProperty()
,则需要使用更复杂的解决scheme。
你可以使用React不变性帮助器来覆盖整个c
,或者把y
的值设置为undefined
或null
。 这取决于你的使用情况,哪个最适合:
const newState = update(state, { c: {$set: { x: '42', }}, });
要么
const newState2 = update(state, { c: { y: {$set: undefined}, }, });