Подтвердить что ты не робот

Удалить значение из объекта без мутации

Какой хороший и короткий способ удалить значение из объекта по определенному ключу без изменения исходного объекта?

Я хотел бы сделать что-то вроде:

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 очень приветствуется.

Большое спасибо!

4b9b3361

Ответ 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}