[js]객체 얕은복사,깊은복사

홍성웅·2024년 2월 23일
0

개요

최근 객체를 복사하여 값을 변경해주는 경우가 있었는데, 원본도 같이 변경되기에 제대로 알아보기 위해 이글을 작성하였다

문제의 코드

 const data = req.body;
 data.password = await bcrypt.hash(req.body.password, 10);

예상한 것은 data의 객체의 password 만 변경되는 거였는데 req.body의 값도 변경되는 것을 보아 참조되는 객체는 주소가 복사가 된다는 의심이 생겼다.

결론은 내 생각이 맞다. 참조값은 주소를 복사한다.

자바스크립트 값

자바스크립트에서는 값이 원시값과 참조값으로 나누어진다.

원시값

  • Number
  • String
  • Boolean
  • Undefined
  • Null

원시값은 값을 복사할때 메모리를 할당하기에 원본의 영향이 가지 않는다.

참조값

  • Symbol
  • Object

하지만 참조값은 변수가 객체의 주소를 가리키게 되어 같은 원본과 같은 주소를 사용한다.

How

그렇다면 어떻게 주소와 상관없이 복사할 수 있을까?

깊은 복사를 해주면 된다.

깊은 복사 (Deep Copy)

재귀 함수를 이용한 복사

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

function copyObj(obj) {
  const result = {};
// for ( key in val) 문법사용
  for (let key in obj) {
    if (typeof obj[key] === 'object') {
      result[key] = copyObj(obj[key]);
    } else {
      result[key] = obj[key];
    }
  }

  return result;
}

const copiedObj = copyObj(obj);

copiedObj.b.c = 3

obj.b.c === copiedObj.b.c //false 

JSON.stringify()

객체를 json으로 바꾸어 주는 동안 주소와의 연결이 끝기기에 json 값을 복사한후 다시 JSON.parse()이용하여 객체로 만들어주면 된다.

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

const copiedObj = JSON.parse(JSON.stringify(obj));

copiedObj.b.c = 3

obj.b.c === copiedObj.b.c //false 

기존의 주소를 복사하는 법

shallow copy 얕은 복사

1. Object.assign()

Object.assign은 첫번째 요소로 들어온 객체에 다음인자로 들어온 객체를 복사해준다.

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

const copiedObj = Object.assign({}, obj);

copiedObj.b.c = 3

obj === copiedObj // false
obj.b.c === copiedObj.b.c // true

2. 전개연산자

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

const copiedObj = {...obj}

copiedObj.b.c = 3

obj === copiedObj // false
obj.b.c === copiedObj.b.c // true
profile
Backend Developer

0개의 댓글