[javascript] 변형없이 객체에서 값 제거

원래 객체를 변경하지 않고 특정 키의 객체에서 값을 제거하는 좋고 짧은 방법은 무엇입니까?

다음과 같은 작업을하고 싶습니다.

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는 매우 환영합니다.

대단히 감사합니다!



답변

최신 정보:

까다로운 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 패키지로 사용할 수 있습니다.


답변

ES7 객체 구조화 사용 :

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


답변

한 줄 솔루션

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


답변

위의 설명에서 제안한대로 objectI like to use 에서 둘 이상의 항목을 제거하기 위해 이것을 확장 하려면 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;
    }


답변

성능을 가져 오는 향신료를 추가합니다. 이 스레드 벨로우즈 확인

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

delete 연산자를 사용하면 V8 히든 클래스 패턴에 성능이 저하됩니다. 일반적으로 사용하지 않는 것이 좋습니다.

또는 개체 고유의 열거 가능한 속성을 제거하려면 해당 속성없이 새 개체 복사본을 만들 수 있습니다 (lodash 사용 예제).

_.omit (o, ‘prop’, ‘prop2’)

또는 속성 값을 null 또는 undefined (JSON으로 직렬화 할 때 암시 적으로 무시 됨)로 정의 할 수도 있습니다.

o.prop = 정의되지 않음

파괴적인 방법도 사용할 수 있습니다.

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.

Undefined는 큰 목록에는 적합하지 않습니다. 또는 많은 소품이 들어 오면서 시간이 지남에 따라 개발됩니다. 메모리 사용량이 계속 증가하고 정리되지 않을 것입니다. 따라서 사용법에 따라 다릅니다. 그리고 새로운 개체를 만드는 것이 좋은 방법 인 것 같습니다.

그런 다음 Premature optimization is the root of all evil의지가 시작됩니다. 따라서 트레이드 오프를 인식해야합니다. 필요한 것과 그렇지 않은 것.

lodash의 _.omit ()에 대한 참고 사항

버전 5에서 제거되었습니다. repo에서 찾을 수 없습니다. 그리고 여기에 그것에 대해 이야기하는 문제가 있습니다.

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

v8

https://v8.dev/blog/fast-properties 좋은 읽기를 확인할 수 있습니다.


답변

ESLint 규칙 표준에서 받아 들여지는 대답에 대한 내 문제는 다음과 같습니다.

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

2 개 개의 새로운 변수, notNeeded그리고 alsoNotNeeded그들이 지금은 사용되지 않는 이후 설정에 따라 경고 또는 오류가 발생 할 수 있습니다. 그렇다면 왜 사용하지 않는 경우 새 변수를 생성합니까?

delete기능을 진정으로 사용해야한다고 생각합니다 .


답변

lodash cloneDeep 및 삭제

(참고 : 얕은 개체 대신 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}