[TIL] 얕은 복사 vs 깊은 복사

기성·2024년 7월 24일
0

TIL

목록 보기
2/81

얕은 복사

객체의 얕은 복사는 복사본의 속성이 복사본이 만들어진 원본 객체와 같은 참조(메모리 내의 같은 값을 가리킴)를 공유하는 복사이다. 따라서 원본이나 복사본을 변경하면 다른 객체 또한 변경될 수 있다. 이러한 동작은 원본과 복사본이 완전히 독립적인 깊은 복사의 동작과 대조적이다.

let obj1 = { name: "Jane", age: "30" };
let obj2 = obj1;

obj2.name = "John";
console.log(obj1, obj2, obj1 === obj2);

그 예시로 이 코드를 들 수 있다.

분명히 obj2의 name을 바꾸었지만 obj1의 name까지 바뀐 것을 알 수 있다.

obj2 = obj1는 데이터의 같은 주소를 참조하게 되어 이러한 결과를 내게 된다.

Spread 연산자 (...)

const obj = {
  a: 1,
  b: {
    c: null,
    d: [1, 2],
  },
};

const obj3 = { ...obj };
obj3.a = 6;
obj3.b.c = 1;
obj3.b.d = [1];

console.log(obj);
console.log(obj3);

여기서 문제는 객체 내부의 객체 데이터는 참조 데이터기 때문에 obj와 obj3둘 다 바뀐 것을 볼 수 있다.

깊은 복사

객체의 깊은 복사는 복사본의 속성이 복사본이 만들어진 원본 객체와 같은 참조를 공유하지 않는 복사이다. 따라서 원본이나 복사본을 변경할 때, 다른 객체가 변경되지 않는 것을 보장할 수 있다. 이러한 동작은 원본이나 복사본의 중첩된 속성을 변경하면 다른 객체도 변경될 수 있는 얕은 복사의 동작과 대조적이다. 쉽게 말해서 얕은 복사처럼 참조할 메모리 주소를 공유하지 않고 값만 복사된 아예 다른 객체를 만들어 내는 것이다. 원본과의 참조가 완전히 끊어진 객체로 볼 수 있다.
깊은 복사를 하기 위해서는 몇가지 방법이 존재한다.

재귀

const copyObjectDeep = function (target) {
  let result = {};
  if (typeof target === "object" && target !== null) {
    for (const prop in target) {
      result[prop] = copyObjectDeep(target[prop]);
    }
  } else {
    result = target;
  }
  return result;
};
const obj = {
  a: 1,
  b: {
    c: null,
    d: [1, 2],
  },
};
const obj2 = copyObjectDeep(obj);

obj2.a = 3;
obj2.b.c = 4;
obj2.b.d[1] = 3;

console.log(obj);
console.log(obj2);

JSON.parse && JSON.stringify

const obj = {
  a: 1,
  b: {
    c: null,
    d: [1, 2],
  },
};

const obj4 = JSON.parse(JSON.stringify(obj));
obj4.a = 6;
obj4.b.c = 1;
obj4.b.d = [1];

console.log(obj);
console.log(obj4);

JSON.stringify()메소드를 통해 객체를 json문자열로 변환한다. 이때 원본 객체와의 참조가 끊어진다고 한다. 그 이후 JSON.parse()로 다시 원래 객체로 변환한다. 단점으로는 속도가 느리고 JSON.stringify()는 함수를 undefined처리한다.
속도 문제는 없는 것 같다.

Object.assign()

const obj = {
  a: 1,
  b: {
    c: null,
    d: [1, 2],
  },
};

const obj5 = Object.assign({}, obj);
obj5.a = 6;
obj5.b.c = 1;
obj5.b.d = [1];

console.log(obj);
console.log(obj5);

Object.assign(생성할 객체, ...복사할 객체)의 방식으로 사용한다. 이 친구의 문제는 2차원 객체는 얕은 복사가 된다는 것이다.

최근에는 복사를 쓸 일이 없어서 관심 밖에 두고 있었는데 깊은 복사에 대해 오랜만에 개념을 다시 정리하게 되었다. 오늘 수업에서 재귀를 본 것 말고도 다른 방식이 있어서 더 알아 보았는데 앞으로도 알음알음하던 개념들을 다시 정리하면서 가야겠다.

profile
프론트가 하고싶어요

0개의 댓글