Front-end/깊게 파고들기

Javascript 얕은복사, 깊은복사

아지송아지 2021. 12. 26. 15:51

이전 글에서 Array.prototype.slice.call()을 하다가 여기까지 왔는데요

하나를 제대로 알기 위해서는 그와 관련된 여러 가지를 알아야 하는 것 같습니다.

 

들어가기 전에 원시값과 참조값에 대하여 간단하게 설명드리겠습니다.

이것 또한 깊이 들어가면 들어갈 수 있지만 이 글에서는 다루지 않겠습니다.

 

원시값은복사할 때 복사된 값을 다른 메모리에 할당하기 때문에 복사를 하더라도 서로에게 영향을 미치지 않습니다.

아래 코드와 같이 a를 b변수에 복사하고 b를 변경한다 하더라도 a가 변경되는 것은 아닙니다.

const a = 1;
let b = a;

b = 2;

console.log(a); // 1
console.log(b); // 2

* 원시값은 String, Number, Boolean, undefined, symbol, null입니다.

 

참조값은 원시값과 달리 복사를 할 때 그대로 복사되는 것이 아닌 "메모리 주소"의 참조값이 복사됩니다.

아래 코드에서처럼 말이죠

const a = {alphabet : "a"};
let b = a;
b.alphabet = "b";

console.log(a); // {alphabet : "b"}
console.log(b); // {alphabet : "b"}

* 참조값은 Object입니다.

 

 

얕은복사 (Shallow copy)


얕은복사의 대표적인 예로는 Object.assign()과 Spread Operator가 있습니다.

 

console.clear();

const obj = {
  a: 1,
  b: {
    c: 2,
  },
};

const newObj = Object.assign({}, obj);
//혹은
const newObj = {...obj};

newObj.b.c = 3

console.log(obj === newObj);// false
console.log(obj.b.c === newObj.b.c )// true

위 코드에서 알 수 있듯  1depth는 false이지만 2depth는 true입니다. 즉 완전히 복사한 것이 아닙니다.

 

2depth이상까지 완벽하게 복사하는 것이 깊은 복사입니다.

 

* NodeList, arguments같은 유사 배열 객체들은 배열로 만들어줍니다.

 

 

깊은복사 (Deep copy)


 

1. 재귀 함수

함수 안에서 함수를 반복적으로 사용하여 새로운 object를 반환합니다.

const obj = {
  a: 1,
  b: {
    c: 2,
  },
};

function copyObj(obj) {
  let result = {};

  for(let key in obj) {
    if(typeof obj[key] === 'object') {
      result[key] = copyObj(obj[key]);
    }else{
      result[key] = obj[key];
    }
  }

  return result;
}

const newObj = copyObj(obj);

2. JSON.parse(JSON.stringify())

object를 문자열로 만들어 참조를 모두 끊은 후 다시 object 형태로 만들어줍니다.

const obj = {
  a: 1,
  b: {
    c: 2,
  },
};
const newObj = JSON.parse(JSON.stringify(obj));

3. lodash - cloneDeep()

라이브러리를 이용하여 만들어줍니다.

const obj = {
  a: 1,
  b: {
    c: 2,
  },
};
const newObj = _.cloneDeep(obj);

 

테스트를 해보면 "재귀 함수 > cloneDeep() > JSON.parse(JSON.stringify())" 순으로 속도가 빠릅니다.

 

'Front-end > 깊게 파고들기' 카테고리의 다른 글

React-Reudx 정리  (0) 2022.01.27
DOM Node, Element 정리  (0) 2022.01.03
Array.prototype.slice.call() 정리, 분석  (0) 2021.12.25
CSR vs SSR (with TTI, TTV, SEO)  (0) 2021.12.16
양방향/단방향 데이터 바인딩  (0) 2021.11.22