[Js]얕은 복사와 깊은 복사

열심히하시는개발자·2021년 4월 15일
0
post-thumbnail

얕은 복사

  • 얕은 복사는 데이터가 그대로 생성되는 것이 아닌 해당 데이터의 참조 값을 전달하여 한 데이터를 공유한다. 즉 중첩된 객체에서 참조형 데이터가 저장된 프로퍼티를 복사할 때 그 주솟값만 복사한다는 의미이다.
let copyObject = function(target) {
  let result = {};
  for(let prop in target) {
    result[prop] = target[prop]
  }
  return result;
} // 기존 정보를 복사해서 새로운 객체를 반환하는 함수(얕은 복사)

let user = {
  name : 'Bj',
  urls : {
    portfolio : "github.com/abc",
    blog : 'blog.com',
    facebook : 'facebook.com/abc',
  }
};

let user2 = copyObject(user) // 얕은 복사 !

user2.name = "Ji";
console.log(user.name === user2.name); // false

user2.urls.portfolio = "portfolio.com";
console.log(user.urls.portfolio === user2.urls.portfolio) // true

user.name === user2.name false가 나오는 이유!

  • user 객체에 직접 속한 프로퍼티에 대해서는 복사해서 완전히 새로운 데이터가 만들어지기 때문

user.urls.portfolio === user2.urls.portfolio true가 나오는 이유!

  • 한 단계 더 들어간 urls의 내부 프로퍼티들은 기존 데이터를 그대로 참조하기 때문

이러한 현상이 발생하지 않도록 하기 위해서는 user.urls 프로퍼티에 대해서도 불변 객체로 만들어 주면 된다.

let user2 = copyObject(user)

user2.urls = copyObject(user.urls);
user.urls.portfolio = "portfolio.com";
console.log(user.urls.portfolio === user2.urls.portfolio) // false

urls 프로퍼티에 copyObject 함수를 실행한 결과를 할당하고 urls 프로퍼티 내부까지 복사해서 새로운 데이터가 만들어졌으므로 console결과 false가 나오는걸 볼 수 있다.

어떤 객체를 복사할 때 객체 내부의 모든 값을 복사해서 완전히 새로운 데이터를 만들고자 할 때 객체의 프로퍼티 중에서 그 값이 기본형 데이터일 경우 그대로 복사되지만 참조형 데이터는 그 내부의 프로퍼티를 복사해야 한다.

깊은 복사

  • 독립적인 메모리에 값 자체를 할당하여 생성한다.

이번에는 copyObject 함수를 깊은 복사 방식으로 바꿔보았다.

let copyObjectDeep = function(target) {
  let result = {};
  if(typeof target === 'object' && target !== null){
    // target !== null 조건을 추가한 이유는 typeof 명령어가 null에 대해서도 object를 반환하기 때문
    for(let prop in target) {
      result[prop] = copyObjectDeep(target[prop]);
    }
  }else{
    result = target;
  }
  return result;
}

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

let obj2 = copyObjectDeep(obj); // 깊은 복사 !
obj2.a = 3;
obj2.b.c = 4;
obj.b.d[1] = 3;

console.log(obj); // { a : 1, b: { c : null, d : [1,3] } }
console.log(obj2); // { a : 3, b: { c : 4, d : [0 : 1, 1 : 2] } }

함수의 인자인 target이 객체인 경우 내부 프로퍼티들을 순회하며 copyObjectDeep 함수를 재귀적으로 호출하고, 객체가 아닌 경우에는 target을 그대로 지정한다.

결론

결론적으로 copyObjectDeep 함수를 사용해 객체를 복사한 다음에 원본과 사본이 서로 다른 객체를 참조하게 되어 어느 쪽의 프로퍼티를 변경하더라도 영향을 주지 않는다.

얕은 복사와 깊은 복사 개념이 명확하게 잡히지 않아서 나름대로 정리를 해보았는데, 아직 헷갈리는 부분도 있지만 기본형 데이터와 참조형 데이터를 복사할 때의 차이점을 알 수 있어서 좋았다.

0개의 댓글