Javascript 从对象中删除值而不发生突变
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33053310/
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 value from object without mutation
提问by amann
What's a good and short way to remove a value from an object at a specific key without mutating the original object?
在不改变原始对象的情况下,从特定键的对象中删除值的好方法是什么?
I'd like to do something like:
我想做类似的事情:
let o = {firstname: 'Jane', lastname: 'Doe'};
let o2 = doSomething(o, 'lastname');
console.log(o.lastname); // 'Doe'
console.log(o2.lastname); // undefined
I know there are a lot of immutability libraries for such tasks, but I'd like to get away without a library. But to do this, a requirement would be to have an easy and short way that can be used throughout the code, without abstracting the method away as a utility function.
我知道有很多用于此类任务的不变性库,但我想在没有库的情况下离开。但是要做到这一点,需要有一种简单而简短的方法,可以在整个代码中使用,而无需将该方法抽象为实用函数。
E.g. for adding a value I do the following:
例如,为了添加一个值,我执行以下操作:
let o2 = {...o1, age: 31};
let o2 = {...o1, age: 31};
This is quite short, easy to remember and doesn't need a utility function.
这很短,易于记忆,不需要实用程序功能。
Is there something like this for removing a value? ES6 is very welcome.
有没有这样的东西来删除一个值?ES6 非常受欢迎。
Thank you very much!
非常感谢!
回答by Leonid Beschastny
Update:
更新:
You could remove a property from an object with a tricky Destructuring assignment:
您可以使用棘手的解构赋值从对象中删除属性:
const doSomething = (obj, prop) => {
let {[prop]: omit, ...res} = obj
return res
}
Though, if property name you want to remove is static, then you could remove it with a simple one-liner:
但是,如果您要删除的属性名称是静态的,那么您可以使用简单的单行删除它:
let {lastname, ...o2} = o
The easiest way is simply toOr you could clone your object before mutating it:
最简单的方法是简单地或者你可以在改变它之前克隆你的对象:
const doSomething = (obj, prop) => {
let res = Object.assign({}, obj)
delete res[prop]
return res
}
Alternatively you could use omit
function from lodash
utility library:
另外,您可以使用omit
从功能lodash
实用程序库:
let o2 = _.omit(o, 'lastname')
It's available as a part of lodashpackage, or as a standalone lodash.omitpackage.
它可以作为lodash包的一部分使用,也可以作为独立的lodash.omit包使用。
回答by senbon
With ES7 object destructuring:
使用 ES7 对象解构:
const myObject = {
a: 1,
b: 2,
c: 3
};
const { a, ...noA } = myObject;
console.log(noA); // => { b: 2, c: 3 }
回答by punksta
one line solution
单线解决方案
const removeKey = (key, {[key]: _, ...rest}) => rest;
回答by ak85
As suggested in the comments above if you want to extend this to remove more than one item from your object
I like to use filter
. and reduce
正如上面评论中所建议的,如果您想扩展它以从您的object
I like to use 中删除多个项目filter
。和reduce
eg
例如
const o = {
"firstname": "Jane",
"lastname": "Doe",
"middlename": "Kate",
"age": 23,
"_id": "599ad9f8ebe5183011f70835",
"index": 0,
"guid": "1dbb6a4e-f82d-4e32-bb4c-15ed783c70ca",
"isActive": true,
"balance": ",510.89",
"picture": "http://placehold.it/32x32",
"eyeColor": "green",
"registered": "2014-08-17T09:21:18 -10:00",
"tags": [
"consequat",
"ut",
"qui",
"nulla",
"do",
"sunt",
"anim"
]
};
const removeItems = ['balance', 'picture', 'tags']
console.log(formatObj(o, removeItems))
function formatObj(obj, removeItems) {
return {
...Object.keys(obj)
.filter(item => !isInArray(item, removeItems))
.reduce((newObj, item) => {
return {
...newObj, [item]: obj[item]
}
}, {})
}
}
function isInArray(value, array) {
return array.indexOf(value) > -1;
}
回答by Mohamed Allal
To add some spice bringing in Performance. Check this thread bellow
添加一些香料,带来性能。检查这个线程波纹管
https://github.com/googleapis/google-api-nodejs-client/issues/375
https://github.com/googleapis/google-api-nodejs-client/issues/375
The use of the delete operator has performance negative effects for the V8 hidden classes pattern. In general it's recommended do not use it.
Alternatively, to remove object own enumerable properties, we could create a new object copy without those properties (example using lodash):
_.omit(o, 'prop', 'prop2')
Or even define the property value to null or undefined (which is implicitly ignored when serializing to JSON):
o.prop = undefined
删除操作符的使用对 V8 隐藏类模式有性能负面影响。一般来说,建议不要使用它。
或者,要删除对象自己的可枚举属性,我们可以创建一个没有这些属性的新对象副本(例如使用 lodash):
_.omit(o, 'prop', 'prop2')
或者甚至将属性值定义为 null 或 undefined(在序列化为 JSON 时会隐式忽略):
o.prop = 未定义
You can use too the destructing way
你也可以使用破坏性的方式
const {remov1, remov2, ...new} = old;
old = new;
And a more practical exmple:
还有一个更实用的例子:
this._volumes[this._minCandle] = undefined;
{
const {[this._minCandle]: remove, ...rest} = this._volumes;
this._volumes = rest;
}
As you can see you can use [somePropsVarForDynamicName]: scopeVarName
syntax for dynamic names. And you can put all in brackets (new block) so the rest will be garbage collected after it.
如您所见,您可以将[somePropsVarForDynamicName]: scopeVarName
语法用于动态名称。您可以将所有内容放在括号中(新块),以便其余部分在它之后被垃圾收集。
exec:
执行:
Or we can go with some function like
或者我们可以使用一些功能,例如
function deleteProps(obj, props) {
if (!Array.isArray(props)) props = [props];
return Object.keys(obj).reduce((newObj, prop) => {
if (!props.includes(prop)) {
newObj[prop] = obj[prop];
}
return newObj;
}, {});
}
for typescript
打字稿
function deleteProps(obj: Object, props: string[]) {
if (!Array.isArray(props)) props = [props];
return Object.keys(obj).reduce((newObj, prop) => {
if (!props.includes(prop)) {
newObj[prop] = obj[prop];
}
return newObj;
}, {});
}
Usage:
用法:
let a = {propH: 'hi', propB: 'bye', propO: 'ok'};
a = deleteProps(a, 'propB');
// or
a = deleteProps(a, ['propB', 'propO']);
This way a new object is created. And the fast property of the object is kept. Which can be important or matter. If the mapping and the object will be accessed many many times.
这样就创建了一个新对象。并且保持了对象的快速属性。这可能很重要或很重要。如果映射和对象会被多次访问。
Also associating undefined
can be a good way to go with. When you can afford it. And for the keys you can too check the value. For instance to get all the active keys you do something like:
关联undefined
也是一个很好的方式。当你买得起的时候。对于键,您也可以检查值。例如,要获取所有活动键,您可以执行以下操作:
const allActiveKeys = Object.keys(myObj).filter(k => myObj[k] !== undefined);
//or
const allActiveKeys = Object.keys(myObj).filter(k => myObj[k]); // if any false evaluated value is to be stripped.
Undefined is not suited though for big list. Or development over time with many props to come in. As the memory usage will keep growing and will never get cleaned. So it depend on the usage. And just creating a new object seem to be the good way.
未定义虽然不适合大列表。或者随着时间的推移,有许多道具进入。因为内存使用量将不断增长并且永远不会被清理。所以这取决于用途。只是创建一个新对象似乎是个好方法。
Then the Premature optimization is the root of all evil
will kick in. So you need to be aware of the trade off. And what is needed and what's not.
然后Premature optimization is the root of all evil
就会开始。所以你需要知道权衡。什么是需要的,什么不是。
Note about _.omit() from lodash
关于 _.omit() 来自 lodash 的注意事项
It's removed from version 5. You can't find it in the repo. And here an issue that talk about it.
它已从版本 5 中删除。您在 repo 中找不到它。这里有一个谈论它的问题。
https://github.com/lodash/lodash/issues/2930
https://github.com/lodash/lodash/issues/2930
v8
v8
You can check this which is a good reading https://v8.dev/blog/fast-properties
你可以检查这是一个很好的阅读https://v8.dev/blog/fast-properties
回答by Jonny
For my code I wanted a short version for the return value of map() but the multiline/mutli operations solutions were "ugly". The key feature is the old void(0)
which resolve to undefined
.
对于我的代码,我想要 map() 返回值的简短版本,但多行/多行操作解决方案“丑陋”。关键特征是旧的void(0)
解决方案undefined
。
let o2 = {...o, age: 31, lastname: void(0)};
The property stays in the object:
该属性保留在对象中:
console.log(o2) // {firstname: "Jane", lastname: undefined, age: 31}
but the transmit framework kills it for me (b.c. stringify):
但是传输框架为我杀死了它(bc stringify):
console.log(JSON.stringify(o2)) // {"firstname":"Jane","age":31}
回答by FFF
with lodash cloneDeep and delete
使用 lodash cloneDeep 并删除
(note: lodash clone can be used instead for shallow objects)
(注意:lodash clone 可以代替浅层对象使用)
const obj = {a: 1, b: 2, c: 3}
const unwantedKey = 'a'
const _ = require('lodash')
const objCopy = _.cloneDeep(obj)
delete objCopy[unwantedKey]
// objCopy = {b: 2, c: 3}