하나의 키를 제외하고 JavaScript 객체를 어떻게 복제 할 수 있습니까?


308

플랫 JS 객체가 있습니다.

{a: 1, b: 2, c: 3, ..., z:26}

하나의 요소를 제외하고 객체를 복제하고 싶습니다.

{a: 1, c: 3, ..., z:26}

가장 쉬운 방법은 무엇입니까 (가능한 경우 es6 / 7을 사용하는 것이 바람직 함)?


원래 객체를 변경하지 않고 : JSON.parse (JSON.stringify ({... obj, 'key2': undefined}))
infinity1975

답변:


441

당신이 사용하는 경우 바벨을 당신은 다음 구문을 사용할 수있는 변수 Y에 속성의 휴식을 복사 한 후 변수 b에 X에서 속성 B를 복사 :

let x = {a: 1, b: 2, c: 3, z:26};
let {b, ...y} = x;

그리고 다음으로 번역 됩니다 :

"use strict";

function _objectWithoutProperties(obj, keys) {
  var target = {};
  for (var i in obj) {
    if (keys.indexOf(i) >= 0) continue;
    if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
    target[i] = obj[i];
  }
  return target;
}

var x = { a: 1, b: 2, c: 3, z: 26 };
var b = x.b;

var y = _objectWithoutProperties(x, ["b"]);

58
사용하지 않는 변수에 대해 코드를 보 푸라하면 "사용하지 않는 변수 'b'가됩니다. 그래도 경고.
Ross Allen

1
만약 당신이 가지고 있다면 문법은 어떻게 let x = [{a: 1, b: 2, c: 3, z:26}, {a: 5, b: 6, c: 7, z:455}];
보일까

14
@RossAllen ignoreRestSiblingsv3.15.0 (2017 년 2 월 3 일)에 추가 된 옵션 이 있습니다. 참조 : commit c59a0ba
Ilya Palkin

4
@IlyaPalkin 재미있는. b범위 가 있다는 사실을 변경하지 않기 때문에 약간 게으른 느낌 입니다.
Ross Allen

2
모듈 빌드 실패 : SyntaxError : 예기치 않은 토큰 인 경우 babel rest spread transform 플러그인을 추가해야합니다. babeljs.io/docs/plugins/transform-object-rest-rest-spread
jsaven

133
var clone = Object.assign({}, {a: 1, b: 2, c: 3});
delete clone.b;

또는 정의되지 않은 속성을 수락하는 경우 :

var clone = Object.assign({}, {a: 1, b: 2, c: 3}, {b: undefined});

7
단순히 속성을 삭제하는 것이 명확하고 간단한 방법입니다.
sshow

24
delete의 단점은 변경 불가능한 작업이 아니라는 것입니다.
Javid Jamae

1
이것은 열쇠를 유지
Fareed Alnamrouti

1
내 의견은 그가 답변을 편집하고 삭제 문을 추가하기 전에 작성되었습니다
Fareed Alnamrouti

이것은 내가 찾던 것이지만 약간 다른 방식으로 약간 더 구현되었습니다. var cake = {... currentCake, requestorId : undefined};
abelito

73

Ilya Palkin의 답변에 추가하려면 키를 동적으로 제거 할 수도 있습니다.

const x = {a: 1, b: 2, c: 3, z:26};

const objectWithoutKey = (object, key) => {
  const {[key]: deletedKey, ...otherKeys} = object;
  return otherKeys;
}

console.log(objectWithoutKey(x, 'b')); // {a: 1, c: 3, z:26}
console.log(x); // {a: 1, b: 2, c: 3, z:26};

바벨 REPL 데모

출처:


3
이것은 좋은 구문입니다.
Hinrich

2
이것은 훌륭하지만 사용하지 않는 var deletedKey를 피할 수있는 방법이 있습니까? 그것이 문제를 일으키는 것이 아니라 JSHint가 불평하게 만들고 실제로 사용하지 않기 때문에 이상하게 보입니다.
Johnson Wong

6
@JohnsonWong 사용 _하지 않을 변수 에 대해 어느 것을 사용할 수 있습니까?
Ryan H.

var b = {a:44, b:7, c:1}; let {['a']:z, ...others} = b; console.log(z , others ); // logs: 44, {b:7, c:1}
jimmont

70

ES6를 사용할 수없는 사람들은 lodash또는 을 사용할 수 있습니다 underscore.

_.omit(x, 'b')

또는 ramda.

R.omit('b', x)

6
생략 을 사용하는 것이 더 논리적이지 않습니까? _.omit(x, 'b')
tibalt

@tibalt에게 감사합니다. 그것으로 답변을 업데이트했습니다.
Noel Llevares

lodash, 밑줄 또는 람다를 사용하는 것은 이미 사용하고 알고있는 프로젝트에만 관련이 있습니다.
jimmont

1
@jimmont delete는 이미 다른 답변에 언급되어 있습니다. 중복 답변이 필요하지 않습니다. 물론 이미 lodash 또는 ramda를 사용하는 사람들에게만 관련이 있습니다. 또한이 답변에 명시된 ES5 및 이전 버전과 관련된 사람들에게만 해당됩니다.
Noel Llevares

@dashmug 내 이전 의견은이 답변에 표시된 접근법을 사용할 때주의해야 할 접근법에 대한 비판이었습니다 (답변이 아님). 답변을 읽고있는 경우이 정보를 원하며 내 의견을 추가하고 언급하는 이유입니다 delete.
jimmont

63

나는이 ESNext 하나의 라이너를 사용

const obj = { a: 1, b: 2, c: 3, d: 4 }
const clone = (({ b, c, ...o }) => o)(obj) // remove b and c
console.log(clone)


범용 기능이 필요한 경우 :

function omit(obj, props) {
  props = props instanceof Array ? props : [props]
  return eval(`(({${props.join(',')}, ...o}) => o)(obj)`)
}

// usage
const obj = { a: 1, b: 2, c: 3, d: 4 }
const clone = omit(obj, ['b', 'c'])
console.log(clone)


9
배열로 포장하는 대신 map다음을 수행 할 수 있습니다.(({b, c, ...others}) => ({...others}))(obj)
bucabay

@bucabay : 훌륭합니다! 그게 가장 좋은 대답입니다! 표준을 준수하고 노드 등에서 완벽하게 작동합니다. 답변으로 제출해야합니다.
david.pfx

3
환상적인 답변 친구 .. <3
Ajithkumar S

5
@totymedli : 내가 아닙니다. 가독성을 높이기 위해 언제든지 마법 기능에 대해 표준 ES6의 일부인 구문 양식을 사용하겠습니다.
david.pfx

1
훌륭한. 그게 다야.
darksoulsong

22

간단한 도우미 함수를 작성할 수 있습니다. Lodash는 같은 이름을 가진 비슷한 기능을 가지고 있습니다 : 생략

function omit(obj, omitKey) {
  return Object.keys(obj).reduce((result, key) => {
    if(key !== omitKey) {
       result[key] = obj[key];
    }
    return result;
  }, {});
}

omit({a: 1, b: 2, c: 3}, 'c')  // {a: 1, b: 2}

또한 Object.assign보다 빠르며 다음을 삭제하십시오. http://jsperf.com/omit-key


11

아마도 이런 식으로 뭔가 :

var copy = Object.assign({}, {a: 1, b: 2, c: 3})
delete copy.c;

이것으로 충분합니까? 아니면 c실제로 복사 할 수 없습니까?


11

객체 파괴 사용

const omit = (prop, { [prop]: _, ...rest }) => rest;
const obj = { a: 1, b: 2, c: 3 };
const objWithoutA = omit('a', obj);
console.log(objWithoutA); // {b: 2, c: 3}


훌륭한 솔루션!
Denys Mikhalenko

2
이 솔루션은 JSLint에서 '사용하지 않은 변수'경고를 막기위한 것 같습니다. 불행하게도, 사용 _ESLint에 대한 문제 ... 해결되지 않습니다
bruynooghe 버트

6

객체를 복사하고 속성을 삭제하려고 할 때 문제를 참조하기 위해 실행되는 것처럼 보입니다. 어딘가에 기본 변수를 할당해야 자바 스크립트가 새로운 가치를 만듭니다.

내가 사용한 간단한 속임수 (끔찍할 수도 있습니다)

var obj = {"key1":"value1","key2":"value2","key3":"value3"};

// assign it as a new variable for javascript to cache
var copy = JSON.stringify(obj);
// reconstitute as an object
copy = JSON.parse(copy);
// now you can safely run delete on the copy with completely new values
delete copy.key2

console.log(obj)
// output: {key1: "value1", key2: "value2", key3: "value3"}
console.log(copy)
// output: {key1: "value1", key3: "value3"}

나는 실제로 그것을 좋아합니다. 할 수 있었다 JSON.parse(JSON.stringify(Object.assign({}, obj, { key2: undefined })));. 그것을 삭제할 필요조차 없으며 거짓 값만 있으면됩니다.
차드

6

아직 언급하지 않은 것으로 보이는 동적 키를 생략하는 옵션은 다음과 같습니다.

const obj = { 1: 1, 2: 2, 3: 3, 4: 4 };
const removeMe = 1;

const { [removeMe]: removedKey, ...newObj } = obj;

removeMe로 별칭이 지정 removedKey되고 무시됩니다. newObj됩니다 { 2: 2, 3: 3, 4: 4 }. 제거 된 키는 존재하지 않으며 값은로 설정되지 않았습니다 undefined.


좋은 해결책. 비슷한 유스 케이스 (감속기의 동적 키)가 있습니다.
ericgio December

4

가장 쉬운 방법

const allAlphabets = {a: 1, b: 2, c: 3, ..., z:26};
const { b, ...allExceptOne } = allAlphabets;
console.log(allExceptOne);   // {a: 1, c: 3, ..., z:26}

3

로다 쉬 생략

let source = //{a: 1, b: 2, c: 3, ..., z:26}
let copySansProperty = _.omit(source, 'b');
// {a: 1, c: 3, ..., z:26}

네, Lodash는 우아한 옵션이지만, 나는 바닐라 ES6와 같은 것을 달성하려고 노력했습니다
andreasonny83

3

스프레드 연산자를 사용하여이를 수행 할 수도 있습니다.

const source = { a: 1, b: 2, c: 3, z: 26 }
const copy = { ...source, ...{ b: undefined } } // { a: 1, c: 3, z: 26 }

2
슈퍼 깔끔한 것 같습니다. 그러나 이것은 키가 정의되지 않은대로 유지합니다copy
kano

거기에 유일한 키가 있다면 정의되지 않은 키를 제거 할 수 있습니다
Victor

1
왜 당신이 사본에 여분의 퍼짐을했는지 확실하지 않고 const copy = { ...source, b: undefined } 정확히 동일하게 끓입니다.
bert bruynooghe 2016

3

구조화를 사용하는 위의 솔루션은 변수를 사용했기 때문에 ESLint에서 불만을 일으킬 수 있다는 사실 때문에 어려움을 겪습니다.

여기 내 해결책이 있습니다.

const src = { a: 1, b: 2 }
const result = Object.keys(src)
  .reduce((acc, k) => k === 'b' ? acc : { ...acc, [k]: src[k] }, {})

대부분의 플랫폼 (Babel을 사용하지 않는 한 IE 제외)에서 다음을 수행 할 수도 있습니다.

const src = { a: 1, b: 2 }
const result = Object.fromEntries(
  Object.entries(src).filter(k => k !== 'b'))


2

거대한 변수를 다루는 경우 비효율적이므로 변수를 복사 한 다음 삭제하고 싶지 않습니다.

hasOwnProperty 검사가있는 간단한 for-loop가 작동해야하며 향후 요구에 훨씬 더 적합합니다.

for(var key in someObject) {
        if(someObject.hasOwnProperty(key) && key != 'undesiredkey') {
                copyOfObject[key] = someObject[key];
        }
}

1
스프레드 연산자 솔루션은 훨씬 좋은 구문으로 정확히 동일합니다.
david.pfx

2

이건 어때? 나는이 패턴을 찾지 못했지만 추가 객체를 만들 필요없이 하나 이상의 속성을 제외하려고했습니다. 이것은 일을하는 것처럼 보이지만 볼 수없는 부작용이 있습니다. 확실히 읽기 쉽지 않습니다.

const postData = {
   token: 'secret-token',
   publicKey: 'public is safe',
   somethingElse: true,
};

const a = {
   ...(({token, ...rest} = postData) => (rest))(),
}

/**
a: {
   publicKey: 'public is safe',
   somethingElse: true,
}
*/

2

내 Redux 감속기의 예와 같이이 방법으로 달성했습니다.

 const clone = { ...state };
 delete clone[action.id];
 return clone;

다시 말해:

const clone = { ...originalObject } // note: original object is not altered
delete clone[unwantedKey]           // or use clone.unwantedKey or any other applicable syntax
return clone                        // the original object without the unwanted key

3 년 전의 대답과 비교할 때 많은 추가 작업처럼 보입니다 (두 옵션 모두 많은 브라우저에서 번역에 의존합니다).
carpiediem

비슷한 유스 케이스 (reducer)가 있으므로 돌연변이없이 동적 키를 지원하는 멋진 방법을 생각해 냈습니다. 기본적으로 : const { [removeMe]: removedKey, ...newObj } = obj;-이 질문에 대한 내 대답을 참조하십시오.
goldins

1

나는 최근에 매우 간단한 방법으로 그것을했다 :

const obj = {a: 1, b: 2, ..., z:26};

스프레드 연산자 를 사용 하여 원치 않는 속성을 분리하십시오.

const {b, ...rest} = obj;

... 및 'rest'부분 만 가져 오도록 object.assign :

const newObj = Object.assign({}, {...rest});

3
rest이미 새로운 객체입니다-마지막 줄이 필요하지 않습니다. 또한 이는 허용되는 솔루션과 동일합니다.
carpiediem

0
const x = {obj1: 1, pass: 2, obj2: 3, obj3:26};

const objectWithoutKey = (object, key) => {
  const {[key]: deletedKey, ...otherKeys} = object;
  return otherKeys;
}

console.log(objectWithoutKey(x, 'pass'));

1
이 코드는 질문에 대한 해결책을 제공 할 수 있지만 왜 / 어떻게 작동하는지에 대한 컨텍스트를 추가하는 것이 좋습니다. 이것은 미래의 사용자가 배우고 그 지식을 자신의 코드에 적용하는 데 도움이 될 수 있습니다. 또한 코드를 설명 할 때 사용자의 의견을 공감 형태로 긍정적으로 평가할 가능성이 있습니다.
borchvm
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.