Какой хороший и короткий способ удалить значение из объекта по определенному ключу без изменения исходного объекта?
Я бы хотел сделать что-то вроде:
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 очень приветствуется.
Большое спасибо!
javascript
immutability
аманн
источник
источник
Ответы:
Обновить:
Вы можете удалить свойство объекта с помощью сложного назначения Destructuring :
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 .
источник
a2 = a1.filter(el => el.id !== id)
пропустить элемент в массиве по определенному идентификатору. Для объекта такого нет?keep_if
const {[prop], ...rest} = obj
работает? Почему вам нужно присвоить извлеченное свойство новой переменной (omit
в данном случае)?no-unused-vars
правило «пропустить» или «пропустить» , это просто регулярное выражение.С деструктуризацией объекта ES7:
const myObject = { a: 1, b: 2, c: 3 }; const { a, ...noA } = myObject; console.log(noA); // => { b: 2, c: 3 }
источник
a
хранится в переменнойconst x = 'a'
?const { a,b, ...noA } = myObject;
console.log(noA); // => {c: 3 }
однострочное решение
const removeKey = (key, {[key]: _, ...rest}) => rest;
источник
Как было предложено в комментариях выше, если вы хотите расширить это, чтобы удалить более одного элемента из вашего,
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; }
источник
Чтобы добавить пикантности в Performance. Проверьте эту резьбу ниже
https://github.com/googleapis/google-api-nodejs-client/issues/375
Вы также можете использовать разрушающий способ
const {remov1, remov2, ...new} = old; old = new;
И более практичный пример:
this._volumes[this._minCandle] = undefined; { const {[this._minCandle]: remove, ...rest} = this._volumes; this._volumes = rest; }
Как видите, вы можете использовать
[somePropsVarForDynamicName]: scopeVarName
синтаксис для динамических имен. И вы можете заключить все в скобки (новый блок), чтобы все остальное было собрано после него.Вот тест:
exec:
Или мы можем использовать какую-нибудь функцию вроде
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
вступит в силу. Итак, вам нужно знать о компромиссе. А что нужно, а что нет.Замечание о _.omit () от lodash
Он удален из версии 5. Вы не можете найти его в репо. И вот вопрос, что об этом поговорим.
https://github.com/lodash/lodash/issues/2930
v8
Вы можете проверить это, и это полезно для чтения https://v8.dev/blog/fast-properties
источник
Моя проблема с принятым ответом из стандарта правил ESLint, если вы попытаетесь деструктурировать:
const { notNeeded, alsoNotNeeded, ...rest } = { ...ogObject };
2 новые переменные,
notNeeded
иalsoNotNeeded
в зависимости от вашей настройки может выдать предупреждение или ошибку, поскольку теперь они не используются. Так зачем создавать новые вары, если они не используются?Я думаю, вам нужно по-настоящему использовать эту
delete
функцию.источник
no-unused-vars
правила есть возможностьignoreRestSiblings
охватить этот вариант использования: eslint.org/docs/rules/no-unused-vars#ignorerestsiblingsс lodash cloneDeep и удалить
(примечание: 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}
источник
Для моего кода мне нужна была короткая версия для возвращаемого значения map (), но решения для операций multiline / mutli были «уродливыми». Ключевой особенностью является старое
void(0)
решениеundefined
.let o2 = {...o, age: 31, lastname: void(0)};
Свойство остается в объекте:
console.log(o2) // {firstname: "Jane", lastname: undefined, age: 31}
но структура передачи убивает меня (bc stringify):
console.log(JSON.stringify(o2)) // {"firstname":"Jane","age":31}
источник