다른 객체에서 객체 속성을 복제하는 방법?


185

주어진 객체 :

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

어떻게 다른 객체 ( secondObject) 안에 속성을 복사 할 수 있습니까?

var secondObject = {
    key1 : 'value1',
    key2 : 'value2',
    key3 : 'value3',
    key4 : 'value4'
};

에 대한 참조를 사용하여 firstObject? 이 같은:

var secondObject = {
    firstObject,
    key3 : 'value3',
    key4 : 'value4'
};

(이것은 작동하지 않습니다 ... 코드를 어떻게 구성하고 싶습니까?

JavaScript 프레임 워크 사용하지 않고도 솔루션이 가능 합니까?



1
문제는 얕거나 깊은 사본을 원하십니까? 깊다면 얼마나 깊습니까?
georg

5
FWIW에서는 "속성"이 아니라 "속성"이라고합니다.
TJ Crowder

그럼에도 불구하고 실제로 작동하는 추악한 것이 있습니다 (실제로는 권장되지 않습니다! 단 하나의 개념 증명).secondObject = JSON.parse('{' + JSON.stringify(firstObject).match(/^.(.*).$/)[1] + ',' + JSON.stringify(secondObject).match(/^.(.*).$/)[1] + '}');
Ben Lee

@ TJCrowder : 질문을 수정했습니다 ... 고마워.
Igor Popov 2019

답변:


213
for(var k in firstObject) secondObject[k]=firstObject[k];

3
@ BenLee, 여기서 당신이 놓친 것은 Igor가 자신이 가지고있는 정확한 사용법을 보여 주었으므로 hasOwnProperty쓸모가 없습니다. 나는 당신의 포인터가 유용하다고 생각하지만, 어떤 상황 에도 규칙을 적용하는 것이 해롭고 현명하지 않다고 생각합니다. 진행중인 이러한 패턴 중심 개발 관행과 마찬가지로 개인적으로 고려하지 마십시오.
Michael Krelin-해커

1
@ MichaelKrelin-hacker, 여기서 누락 된 것은 StackOverflow가 OP의 이익을위한 것이 아니라는 것입니다. 포인터 유용 할 수 있는 사용 사례가 약간 다른 미래 방문자를위한 참조로 사용됩니다 .
벤 리

@ BenLee, 나는 IgorPopov가 아닙니다 ;-) 그리고 OP가 아니기 때문에 이미 포인터가 유용하고 귀하의 답변을 찾았다 고 말한 것은 내가 싫어하는 "당신은 정말로 사용해야합니다"부분입니다.
Michael Krelin-해커

23
당신은 hasOwnProperty()테스트를 생략 하고 일이 계속 작동합니다. 시간이 지남에 따라 객체가 더 복잡해지기 때문에 중지 할 때까지. 그렇지 않으면 코드가 너무 많이 복사되어 코드의 관련되지 않은 부분에서 신비 로워집니다. 그리고 디버깅에 대한 컨텍스트가 없습니다. JS는 그렇게 짜증나므로 이러한 문제가 발생하지 않도록주의해서 코딩하는 것이 중요합니다.
Eli Bendersky

2
이 답변은 다음 링크에 따라 업데이트되어야한다고 생각합니다. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… const target = {a : 1, b : 2}; const 소스 = {b : 4, c : 5}; const returnedTarget = Object.assign (대상, 소스); console.log (대상); // 예상 출력 : Object {a : 1, b : 4, c : 5} console.log (returnedTarget); // 예상 출력 : Object {a : 1, b : 4, c : 5}
Elbassel

170

@ Bardzuśny의 대답에서 힌트를 얻은 ES6는 기본 솔루션 인 Object.assign()기능을 제공했습니다.

사용법은 간단합니다.

Object.assign(secondObject, firstObject);

그게 다야!

현재의 지원은 분명히 좋지 않습니다. Firefox (34+) 만 기본적으로 지원하며 Chrome (45+) 및 Opera (32+)에는 '실험용 플래그'를 설정해야합니다.

최신 버전의 Chrome, Firefox, Opera, Safari 및 Edge를 지원하여 지원이 향상되고 있습니다 (IE는 지원하지 않습니다). Babel 및 Traceur와 같은 트랜스 파일러도 사용할 수 있습니다. 자세한 내용은 여기 를 참조하십시오.


4
+1, 또 다른 멋진 ES6 기능. 물론 브라우저 / Node.JS 지원은 현재 부족하지만 언급했듯이 사용할 수있는 변환기가 있습니다. 그리고 마음에 들지 않으면 shim : github.com/paulmillr/es6-shim (또는 독립형 Object.assign()shim : github.com/ljharb/object.assign )을 사용하십시오.
bardzusny

1
@Xoyce 연결된 MDN 페이지를 확인하면 "원본 값이 개체에 대한 참조 인 경우 해당 참조 값만 복사합니다"라고 명확하게 표시됩니다. 따라서 실제로 참조를 유지하고 개체를 복사하지 않습니다. 예기치 않은 행동에 대한 귀하의 경고는 여전히 적절하며, 적절한 기대치를 가지고 있습니다.
DIMM Reaper

@mostafiz이 페이지의 질문과 다른 답변은 "firstObject"와 "secondObject"라는 이름을 사용하기 때문에 편집 내용을 롤백 했으므로 명확성과 일관성을 위해 여기에 동일한 이름을 사용했습니다.
DIMM Reaper

이것이 질문과 일치하면 괜찮습니다.
Mostafiz Rahman

1
@pdem Yep- kingPuppy의 답변을 참조하십시오 .
DIMM Reaper

101

ES6-확산 구문 :

간단하게 사용할 수 있습니다 :

const thirdObject = {
   ...firstObject,
   ...secondObject   
}

이를 통해 이러한 객체를 참조로 전달할 때 발생하는 문제를 피할 수 있습니다.

또한 중첩이 깊은 개체를 처리합니다.


2
와우, 이것은 정말로 굉장하다 :) 답변 주셔서 감사합니다. 분명히, 나는 더 이상 필요하지 않지만 (이전에는 있었기 때문에) 다른 누군가를 도울 수 있습니다.
Igor Popov

1
ES6의 더 멋진 사용법을 위해 +1! 위에서 언급 한 MDN 문서는 객체에 스프레드 연산자를 사용하는 것에 대해 언급하지 않았으므로, 실제 동작을 확인하기 위해 바이올린을 만들었습니다. es6fiddle.net/im3ifsg0
DIMM Reaper

1
@ jaepage-참조를 위해 좋은 의견. 간단한 속성 이름을 가진 객체 (원래 질문에 따라) 반복 가능합니다.
kingPuppy

1
Chrome에서 작동하며 ES6이므로 현재 Babel 또는 일부 ES6 트랜스 필러가 필요합니다. 앞으로 모든 브라우저는이 구문을 지원할 것으로 예상됩니다.
kingPuppy

89

첫 번째 객체의 속성을 반복하여 다음과 같이 두 번째 객체에 할당합니다.

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

var secondObject = {
    key3 : 'value3',
    key4 : 'value4'
};

for (var prop in firstObject) {
    if (firstObject.hasOwnProperty(prop)) {
        secondObject[prop] = firstObject[prop];
    }
}

for- in루프는 충분하지 않다; 당신은 필요합니다 hasOwnProperty. 이유에 대한 자세한 설명은 http://bonsaiden.github.com/JavaScript-Garden/#object.forinloop 를 참조하십시오 .


@RobW, OP가 reference기술적 인 의미로 사용 하고 있다고 생각하지 않았습니다 . 나는 그가 단지 "언어하는"을 의미한다고 생각한다.
벤 리

1
@RobW : OP는 실제로 "복사"라고했습니다.
TJ Crowder

49

ES5가 우리를 가져 왔기 때문에 네크로맨서를 연주하면 Object.keys()이 모든 .hasOwnProperty()수표 에서 우리를 구할 수 있습니다.

Object.keys(firstObject).forEach(function(key) {
  secondObject[key] = firstObject[key];
});

또는 함수로 묶기 (lodash의 "복사"로 제한 _.assign()) :

function assign(object, source) {
  Object.keys(source).forEach(function(key) {
    object[key] = source[key];
  });
}

assign(secondObject, firstObject); // assign firstObject properties to secondObject

Object.keys()IE <9에서는 사용할 수없는 비교적 새로운 방법입니다. 실제로는 .forEach()규칙 방법 대신 사용한 배열 방법도 마찬가지 입니다.for 루프 합니다.

운 좋게도 es5-shim이 있습니다 이 고대 브라우저에서 사용할 수있는 있으며,이 브라우저는 많은 ES5 기능 (그 둘을 포함하여)을 채울 것입니다.

(멋지고 새로운 언어 기능을 사용하는 것을 막는 것이 아니라 폴리 필을 사용하는 것이 전부입니다.)


갑자기 2 명은 어디에서나 공감할 수 있습니다. 그 사람들 이이 의견을 읽을 가능성이 적습니다. 실제 이유는 무엇입니까? 내 대답에서 변경 / 개선 할 것을 제안하는 것이 있습니까?
bardzusny

1
이것은 분명히 객체 확산 이니셜 라이저 (ES6)뿐만 아니라 맨 위로 올라갈 가치가 있습니다. 이것은 화살표 기능으로 더 깨끗해 보입니다!
mjohnsonengr

12

사람들은 hasOwnProperty와 실제 객체 검사를 통해 깊은 복사 방법을 찾을 수 있습니다.

var extend = function (original, context, key) {
  for (key in context)
    if (context.hasOwnProperty(key))
      if (Object.prototype.toString.call(context[key]) === '[object Object]')
        original[key] = extend(original[key] || {}, context[key]);
      else
        original[key] = context[key];
  return original;
};

이것은 배열이나 함수 객체를 딥 카피하지는 않지만 다른 모든 종류의 객체를 딥 카피합니다.
매트 브라운

1
예, 배열을 딥 카피하려면 타입 체크를 수정하여'[object Array]'
Nijikokun

12

Object.assign 을 사용할 수 있습니다 을 하여 객체를 결합 . 공통 속성을 오른쪽에서 왼쪽으로 결합하고 재정의합니다. 즉 왼쪽의 동일한 속성이 오른쪽으로 재정의됩니다.

그리고는 중요한 소스 오브젝트를 돌연변이 피하기 위해 먼저 빈 객체를 제공 할 수 있습니다. 소스 객체는 다음과 같이 깨끗하게 유지해야합니다Object.assign() 자체는 새 객체를 반환하므로 합니다.

도움이 되었기를 바랍니다!

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

var secondObject = {
    key3 : 'value3',
    key4 : 'value4'
};

var finalObject = Object.assign({}, firstObject, secondObject)

console.log(finalObject)


하지만 당신은 어떤 경우 원하는 것이 첫 번째 개체를 돌연변이? 객체 A와 객체 B가 있고 모든 속성이 객체 B의 속성과 동일하도록 객체 A를 변경하고 싶습니까? Object.assign (A, B) 하시겠습니까?
TKoL

해당 Mozilla 개발자 네트워크 페이지에 따라 IE, Android WebView, Android Opera에서 슬프게도 지원되지 않습니다.
Yetti99

6

kingPuppy 아이디어 및 OP 아이디어 개선 (얕은 복사) -OP "example"에 3 개의 점만 추가합니다. :)

var secondObject = {
    ...firstObject,
    key3 : 'value3',
    key4 : 'value4'
};


4

이것은 여기 에서 테스트되고 작동 합니다 .

var secondObject = {
    firstObject: JSON.parse(JSON.stringify(firstObject)),
    key3 : 'value3',
    key4 : 'value4'
};

참고 :이 방법은 firstObject
참고 2의 방법을 복사하지 않습니다 . 이전 브라우저에서 사용하려면 json 파서 가 필요합니다.
주 3 : 참조로 할당하는 것은 특히 옵션이 firstObject포함되어있는 경우에 실행 가능한 옵션 입니다. 주어진 jsfiddle 예제를 적절히 조정했습니다.


3

불행히도, 그런 객체에 변수에 대한 참조를 넣을 수는 없습니다. 그러나 객체 값을 다른 객체로 복사하는 기능을 만들 수 있습니다.

function extend( obj1, obj2 ) {
    for ( var i in obj2 ) {
        obj1[i] = obj2[i];
    }
    return obj1;
}

var firstObject = {
    key1: "value1",
    key2: "value2"
};

var secondObject = extend({
    key3: "value3",
    key4: "value4"
}, firstObject );

기본 속성도 복사됩니다. 그리고 객체 자체 인 속성은 어떻습니까?
KooiInc

1

당신이 잡아 원하는 경우 에만 두 번째 개체에 존재하는 속성을, 당신이 사용할 수있는 Object.keys두 가지 방법을 할 수있는 첫 번째 개체의 속성을 잡아 :

A.) map 부작용을 사용하여 첫 번째 개체의 속성을 두 번째 개체에 할당합니다.

var a = {a:100, b:9000, c:300};
var b = {b:-1};

Object.keys(a).map(function(key, index) {
    if (typeof b[key] !== 'undefined') {
        console.log(key);
        b[key] = a[key];    
    }
});

B.) 또는 reduce새 개체를 만들어 두 번째 개체에 할당합니다. 이 메소드 첫 번째 오브젝트와 일치하지 않는 두 번째 오브젝트가 가질 수있는 다른 특성을 대체 합니다.

var a = {a:100, b:9000, c:300};
var b = {b:-1, d:-1}; // d will be gone

b = Object.keys(a).reduce(function(result, current) {
    if (typeof b[current] !== 'undefined') {
        result[current] = a[current];   
    }
    return result;
}, {});

1

속성 스프레드 표기법을 사용하십시오. ES2018에 추가되었으며 (배열 / 이터 블에 대한 확산은 이전, ES2015) {... firstObject}는 모든 열거 가능한 속성을 개별 속성으로 분산시킵니다.

let secondObject = {
      ...firstObject,
      key3 : 'value3',
      key4 : 'value4'
    }

귀하의 답변에 대한 문맥과 그에 대한 문제를 해결하는 이유를 알려주시겠습니까?
Tamir Klein

0

오히려 firstObject를 secondObject의 프로토 타입으로 사용하고 속성 설명자를 추가합니다.

var secondObject = Object.create(firstObject, {
      key3: {value: "value3", writable: true, configurable: true, enumerable: true},
      key4: {value: "value4", writable: true, configurable: true, enumerable: true}
      });

확실히 하나의 라이너는 아니지만 더 많은 제어 기능을 제공합니다. 속성 설명자에 관심이 있으시면 http://patrickdelancy.com/2012/09/property-descriptors-in-javascript/#comment-2062 및 MDN 페이지 https : //developer.mozilla 를 읽어보십시오 . org / en-US / docs / Web / JavaScript / Reference / Global_Objects / Object / create

값을 할당하고 설명자를 생략하고 조금 더 짧게 만들 수도 있습니다.

var secondObject = Object.create(firstObject, {
      key3: {value: "value3"}
      key4: {value: "value4"}
  });

호환성 : ECMAScript 5, IE9 +


0
var firstObject = {
     key1: "value1",
     key2: "value2"
};

var secondObject = {
     key3: "value3",
     key4: "value4"
     copy: function(firstObject){
           this.key1 = firstObject.key1;
           this.key2 = firstObject.key2;
     }
 };

다음 방법을 사용하면 속성이 복사됩니다.

secondObject.copy(firstObject)

나는 자바 스크립트를 처음 접했지만이 작업을 발견했습니다. 조금 너무 오래 추측하지만 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.