不变异地从对象中移除值

在不改变原始对象的情况下,从一个特定键的对象中删除一个值的好方法是什么?

我想做这样的事情:

let o = {firstname: 'Jane', lastname: 'Doe'};
let o2 = doSomething(o, 'lastname');
console.log(o.lastname); // 'Doe'
console.log(o2.lastname); // undefined

我知道有很多不变性库可以用来完成这样的任务,但是我希望没有不变性库。但是要做到这一点,需要有一个简单而简短的方法,可以在整个代码中使用,而不是将方法抽象为一个实用函数。

例如,为了增加一个值,我会做以下操作:

let o2 = {...o1, age: 31};

这是相当短,容易记住,不需要实用功能。

有没有类似这样的去除值的方法? ES6非常受欢迎。

非常感谢!

107868 次浏览

更新:

你可以用一个复杂的 破坏任务从一个对象中移除一个属性:

const doSomething = (obj, prop) => {
let {[prop]: omit, ...res} = obj
return res
}

不过,如果您想删除的属性名是静态的,那么您可以使用一个简单的一行程序来删除它:

let {lastname, ...o2} = o

最简单的方法就是简单的 或者你可以在变异之前克隆你的对象:

const doSomething = (obj, prop) => {
let res = Object.assign({}, obj)
delete res[prop]
return res
}

或者你可以使用 ABC1实用程序库中的 omit函数:

let o2 = _.omit(o, 'lastname')

它可以作为 浪荡软件包的一部分,也可以作为独立的 Lodash 省略软件包使用。

正如上面的评论所建议的,如果你想扩展这个来从你的 object中移除多个项目,我喜欢使用 filter。和 reduce

例句

    const o = {
"firstname": "Jane",
"lastname": "Doe",
"middlename": "Kate",
"age": 23,
"_id": "599ad9f8ebe5183011f70835",
"index": 0,
"guid": "1dbb6a4e-f82d-4e32-bb4c-15ed783c70ca",
"isActive": true,
"balance": "$1,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;
}

一线解决方案

const removeKey = (key, {[key]: _, ...rest}) => rest;

解说:

这是一个用于删除特定键的通用箭头函数。第一个参数是要删除的键的名称,第二个参数是要从中删除键的对象。注意,通过重新构造它,我们生成策划的结果,然后返回它。

例如:

let example = {
first:"frefrze",
second:"gergerge",
third: "gfgfg"
}


console.log(removeKey('third', example))
/*
Object {
first: "frefrze",
second: "gergerge"
}
*/

使用 ES7对象解构:

const myObject = {
a: 1,
b: 2,
c: 3
};
const { a, ...noA } = myObject;
console.log(noA); // => { b: 2, c: 3 }

用 loash cloneDeep 和 delete

(注意: 对于浅对象可以使用 loash 克隆)

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}

为了增加一些香料带来的性能。检查下面的线程

Https://github.com/googleapis/google-api-nodejs-client/issues/375

删除操作符的使用对 V8隐藏类模式。通常建议不要使用 它。

或者,要删除对象自己的可枚举属性,我们可以 创建一个没有这些属性的新对象副本(示例使用 罗达什) :

_. 省略(o,’道具’,’道具2’)

或者甚至将属性值定义为 null 或未定义(即 在序列化到 JSON 时隐式忽略) :

没有定义

你也可以用毁灭的方式

const {remov1, remov2, ...new} = old;
old = new;

还有一个更实际的例子:

this._volumes[this._minCandle] = undefined;
{
const {[this._minCandle]: remove, ...rest} = this._volumes;
this._volumes = rest;
}

如您所见,可以对动态名称使用 [somePropsVarForDynamicName]: scopeVarName语法。并且您可以将所有内容放在括号(新块)中,这样其余内容将在其后进行垃圾收集。

这里有一个测试: enter image description here

执行:

enter image description here

或者我们可以用

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;
}, {});
}

打字稿

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;
}, {});
}

用法:

let a = {propH: 'hi', propB: 'bye', propO: 'ok'};


a = deleteProps(a, 'propB');


// or


a = deleteProps(a, ['propB', 'propO']);

这样就创建了一个新对象。并且保持了对象的快速性。可能是重要的,也可能是重要的。如果映射和对象将被多次访问。

同样,将 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.

未定义不适合大名单。或发展随着时间的推移,许多道具进来。因为内存使用量将不断增长,永远不会被清理。所以它取决于用法。只是创建一个新的对象似乎是好的方式。

然后 Premature optimization is the root of all evil就会生效。所以你需要注意权衡利弊。需要什么,不需要什么。

请注意 loash 中的 _. omit ()

它从版本5中删除了。你不能在回购中找到它。这里有一个问题谈论它。

Https://github.com/lodash/lodash/issues/2930

V8引擎

你可以检查这是一个很好的阅读 https://v8.dev/blog/fast-properties

对于我的代码,我想要一个关于 map ()返回值的简短版本,但是多行/mutli 操作解决方案是“丑陋的”。关键特性是解析为 undefined的旧 void(0)

let o2 = {...o, age: 31, lastname: void(0)};

属性保留在对象中:

console.log(o2) // {firstname: "Jane", lastname: undefined, age: 31}

但是传输框架为我扼杀了它(B.C. stringify) :

console.log(JSON.stringify(o2)) // {"firstname":"Jane","age":31}

如果您试图解构:

    const { notNeeded, alsoNotNeeded, ...rest } = { ...ogObject };

2个新变量,notNeededalsoNotNeeded可能会抛出一个警告或错误取决于您的设置,因为他们现在不使用。那么,如果没有使用,为什么要创建新的 var 呢?

我认为你需要真正使用 delete函数。

我为自己写了一个关于问题的大函数。该函数清除所有的道具值(不是本身,只有值) ,数组等作为多维。

注意: 函数 clear 元素在数组和数组中变成空数组。也许这种情况下可以添加到功能作为可选的。

Https://gist.github.com/semihkeskindev/d979b169e4ee157503a76b06573ae868

function clearAllValues(data, byTypeOf = false) {


let clearValuesTypeOf = {
boolean: false,
number: 0,
string: '',
}


// clears array if data is array
if (Array.isArray(data)) {
data = [];
} else if (typeof data === 'object' && data !== null) {
// loops object if data is object
Object.keys(data).forEach((key, index) => {
// clears array if property value is array
if (Array.isArray(data[key])) {
data[key] = [];
} else if (typeof data[key] === 'object' && data !== null) {
data[key] = this.clearAllValues(data[key], byTypeOf);
} else {
// clears value by typeof value if second parameter is true
if (byTypeOf) {
data[key] = clearValuesTypeOf[typeof data[key]];
} else {
// value changes as null if second parameter is false
data[key] = null;
}
}
});
} else {
if (byTypeOf) {
data = clearValuesTypeOf[typeof data];
} else {
data = null;
}
}


return data;
}

下面是一个不使用删除道具清除所有值的示例

let object = {
name: 'Semih',
lastname: 'Keskin',
brothers: [
{
name: 'Melih Kayra',
age: 9,
}
],
sisters: [],
hobbies: {
cycling: true,
listeningMusic: true,
running: false,
}
}


console.log(object);
// output before changed: {"name":"Semih","lastname":"Keskin","brothers":[{"name":"Melih Kayra","age":9}],"sisters":[],"hobbies":{"cycling":true,"listeningMusic":true,"running":false}}


let clearObject = clearAllValues(object);


console.log(clearObject);
// output after changed: {"name":null,"lastname":null,"brothers":[],"sisters":[],"hobbies":{"cycling":null,"listeningMusic":null,"running":null}}


let clearObject2 = clearAllValues(object);


console.log(clearObject2);
// output after changed by typeof: {"name":"","lastname":"","brothers":[],"sisters":[],"hobbies":{"cycling":false,"listeningMusic":false,"running":false}}
export function deleteKeyFromObject(obj, key) {
return Object.fromEntries(Object.entries(obj).filter(el => el[0] !== key))
}