不可移动地移除对象中的属性

我正在使用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的数组方法像filtermapreduce有用的,因为他们总是返回新的数组或对象。 在这种情况下,我会使用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的值设置为undefinednull 。 这取决于你的使用情况,哪个最适合:

 const newState = update(state, { c: {$set: { x: '42', }}, }); 

要么

 const newState2 = update(state, { c: { y: {$set: undefined}, }, });