본문 바로가기
javaScript

javaScript - 객체의 병합(깊은 복사, 얕은 복사)

by sinabeuro 2021. 8. 5.
728x90

객체 복사는 기본적으로 원본 객체의 주소값을 참조합니다.

복사된 객체와 원본 객체 간의 연결고리 계속이어지며, 한쪽을 바꾸면 복사된 객체와 원본 객체의 값 전부가 바뀌게 됩니다.

 

이러한 복사된 객체와 원본 객체 간의 연결고리를 끊으려면 어떻게 해야할까요?

또한 1뎁스 객체의 연결고리를 끊더라도 2뎁스는 원본 객체를 참조하는 경우, 이를 얕은 복사라고 합니다.

반면 모든 뎁스의 연결고리를 끊는 것을 깊은 복사라고 합니다.

 

 

  • 깊은 복사
const sourceObject = {
  traits: {
    value: 'Bob',
    source_id: 1,
    updated_at: 1623238587468
  },
  emails_opend_last_30_days: {
    value: 33,
    source_id: 2,
    updated_at: 1623238601089
  },
  cursor: {
    url: '/v1/spaces/lgJ4AAjFN4',
    has_more: false,
    next: ''
  }
};

// 깊은 복사
const newObject1 = JSON.parse(JSON.stringify(sourceObject));

가장 손쉬운 방법으로 JSON.stringify 방식이 있는데 이 방법이 손쉽게 객체의 연결고리를 끊을 수는 있지만, 성능이 그다지 좋지않아 객체의 크기가 크다면 다른 방법으로 접근해야합니다.

 

  • 얕은 복사
const newObject2 = Object.assign({}, sourceObject);
const newObject3 = {...sourceObject};
console.log(newObject2);
console.log(newObject3);

1뎁스만 복사하기 때문에 1뎁스 안에 있는 또 다른 객체들은 그대로 참조로 넘어가게 되는 문제를 갖고 있습니다.

 

JSON.parse를 이용하지 않고 깊은 복사를 하기 위해서는 따로 함수를 만들어야합니다.

function deepCopyObject(obj) {
  const clone = {};
  for(const key in obj) {
    if(typeof obj[key] == 'object' && obj[key] != null) {
      clone[key] = deepCopyObject(obj[key]);
    } else {
      clone[key] = obj[key]
    }
  }
  return clone;
}

const newObject4 = deepCopyObject(sourceObject)
console.log(newObject4);

복사할 객체가 2뎁스이상이거나 객체배열구조일 경우에는 재귀함수를 실행하여 하위 뎁스까지 하나씩 하나씩 복사합니다. 

이러한 로직에 의해 하위뎁스 또는 배열인자 하나하나 복사되어 깊은 복사가 구현되는 것입니다.

 

 

깊은 복사를 한 객체의 일부를 변경하여 반환하고 싶은 경우

const store = {
  user: null,
  cart: [],
  config: {
    multiDevice: false,
    lastLoginDate: 'Wed Jun 09 2021 20:46:55 GMT+0900'
  }
}

const newObject5 = {
  ...deepCopyObject(sourceObject),	// 깊은 복사 진행
  config: {
    ...store.config,	// 객체 덮어 쓰기를 방지하기 위한 전개연산자
    lastLoginDate: new Date(),	// 복사한 객체의 변경 부분
  },
};

console.log(newObject5);

복사 객체가 2뎁스 이상인 경우 변경할 객체 뎁스에 객체 덮어쓰기 방지를 위한 코드가 필요합니다.

config: {
  ...store.config,

  lastLoginDate: new Date(),

}

 

 

 

객체 일부를 변경하여 새로운 객체를 반환하고 싶은 경우

const DefaultStyle = {
  color: '#fff',
  fontColor: '#999',
  fontSize: 14,
  fontWeight: 200,
};

function createParagraph(config) {
  config = {...DefaultStyle, ...config};
  return config;
}

console.log(createParagraph({ fontSize: 12 }));

 

 

 

 

728x90

'javaScript' 카테고리의 다른 글

javaScript - html의 event, this 활용하기  (0) 2021.12.13
javaScript - 프로세싱 코드모음  (0) 2021.08.04
javaScript - closure 기법  (0) 2021.07.28
javaScript - context 문법  (0) 2021.07.27
javaScript - 배열2 배열 연산  (0) 2021.07.22

댓글