Удалить значение из объекта без мутации
Какой хороший и короткий способ удалить значение из объекта по определенному ключу без изменения исходного объекта?
Я хотел бы сделать что-то вроде:
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 очень приветствуется.
Большое спасибо!
Ответы
Ответ 1
Update:
Вы можете удалить свойство из объекта с помощью сложного назначения деструктурирования:
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
}
В качестве альтернативы вы можете использовать omit
функцию из lodash
утилиты:
let o2 = _.omit(o, 'lastname')
Он доступен как часть пакета lodash или как отдельный lodash.omit пакет.
Ответ 2
С деструктуризацией объекта ES7:
const myObject = {
a: 1,
b: 2,
c: 3
};
const { a, ...noA } = myObject;
console.log(noA); // => { b: 2, c: 3 }
Ответ 3
решение одной линии
const removeKey = (key, {[key]: _, ...rest}) => rest;
Ответ 4
Как указано в комментариях выше, если вы хотите расширить это, чтобы удалить более одного элемента из вашего 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;
}
Ответ 5
Чтобы добавить некоторые специи, приносящие производительность. Проверьте эту тему ниже
https://github.com/googleapis/google-api-nodejs-client/issues/375
Использование оператора удаления имеет негативные последствия для производительности шаблон скрытых классов V8. В общем, рекомендуется не использовать это.
В качестве альтернативы, чтобы удалить собственные перечисляемые свойства объекта, мы могли бы создать новую копию объекта без этих свойств (например, используя lodash):
_.omit(o, 'prop', 'prop2')
Или даже определите значение свойства как нулевое или неопределенное (что игнорируется при сериализации в JSON):
o.prop = undefined
Вы можете использовать слишком разрушительный способ
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]()
Exec:
![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.
Undefined не подходит для большого списка. Или развитие со временем с большим количеством реквизита. Поскольку использование памяти будет расти и никогда не будет очищено. Так что это зависит от использования. И просто создание нового объекта кажется хорошим способом.
Затем сработает Premature optimization is the root of all evil
. Так что вам нужно знать о компромиссе. И что нужно, а что нет.
Примечание о _.omit() от lodash
Он удален из версии 5. Вы не можете найти его в репозитории. И тут вопрос, который об этом говорит.
https://github.com/lodash/lodash/issues/2930
v8
Вы можете проверить это, что является хорошим чтением https://v8.dev/blog/fast-properties
Ответ 6
с lodash clone углубиться и удалить
(примечание: вместо мелких предметов можно использовать клон lodash)
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}