Javascript 不可变地删除对象中的属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34401098/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Remove a property in an object immutably
提问by Vincent Taing
I am using Redux. In my reducer I'm trying to remove a property from an object like this:
我正在使用 Redux。在我的减速器中,我试图从这样的对象中删除一个属性:
const state = {
a: '1',
b: '2',
c: {
x: '42',
y: '43'
},
}
And I want to have something like this without having to mutate the original state:
我想拥有这样的东西而不必改变原始状态:
const newState = {
a: '1',
b: '2',
c: {
x: '42',
},
}
I tried:
我试过:
let newState = Object.assign({}, state);
delete newState.c.y
but for some reasons, it deletes the property from both states.
但由于某些原因,它从两个州中删除了该财产。
Could help me to do that?
可以帮我做吗?
回答by madebydavid
How about using destructuring assignmentsyntax?
如何使用解构赋值语法?
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 } }
回答by David L. Walsh
I find ES5 array methods like filter
, map
and reduce
useful because they always return new arrays or objects. In this case I'd use Object.keys
to iterate over the object, and Array#reduce
to turn it back into an object.
我发现 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;
}, {})
});
回答by Dmitri
回答by Ramon Diogo
Just use ES6 object destructuring feature
只需使用 ES6 对象解构功能
const state = {
c: {
x: '42',
y: '43'
},
}
const { c: { y, ...c } } = state // generates a new 'c' without 'y'
console.log({...state, c }) // put the new c on a new state
回答by A???
That's because you are copying the value of state.c
to the other object. And that value is a pointer to another javascript object. So, both of those pointers are pointing to the same object.
那是因为您正在将 的值复制state.c
到另一个对象。该值是指向另一个 javascript 对象的指针。所以,这两个指针都指向同一个对象。
Try this:
尝试这个:
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.c.y;
You can also do a deep-copy of the object. See this questionand you'll find what's best for you.
您还可以对对象进行深层复制。看到这个问题,你会找到最适合你的。
回答by SebK
How about this:
这个怎么样:
function removeByKey (myObj, deleteKey) {
return Object.keys(myObj)
.filter(key => key !== deleteKey)
.reduce((result, current) => {
result[current] = myObj[current];
return result;
}, {});
}
It filters the key that should be deleted then builds a new object from the remaining keys and the initial object. The idea is stolen from Tyler McGinnes awesome reactjs program.
它过滤应该删除的键,然后从剩余的键和初始对象构建一个新对象。这个想法是从 Tyler McGinnes 很棒的 reactjs 程序中窃取的。
回答by Dominykas Mostauskis
回答by Javier P
You may use Immutability helperin order to unset an attribute, in your case:
您可以使用Immutability helper来取消设置属性,在您的情况下:
import update from 'immutability-helper';
const updatedState = update(state, {
c: {
$unset: ['y']
}
});
回答by jian
As of 2019, another option is to use the Object.fromEntries
method. It has reached stage 4.
截至 2019 年,另一种选择是使用该Object.fromEntries
方法。它已经达到了第 4 阶段。
const newC = Object.fromEntries(
Object.entries(state.c).filter(([key]) => key != 'y')
)
const newState = {...state, c: newC}
The nice thing about it is that it handles integer keys nicely.
它的好处是它可以很好地处理整数键。