[JavaScript] 깊은복사, 얕은복사

2022. 7. 10. 19:28WEB/Javascript

 

 

JavaScript에서 객체를 공부하다 객체를 복사할 때 의문이 생겼다. 객체를 복사한 후 복사한 객체를 수정했더니 원본 객체의 값이 변했다 왜그럴까?

let a = {name : "K"}
let b = a;
b.name = "D";

console.log(a.name) // D가 출력됨
console.log(a===b) // true;

 

대입연산으로 객체를 변수에 할당하면 원래 객체의 주소값이 할당 됨을 확인 할수 있었다.

이것을 얕은 복사라고 말하고 '참조에 의한 객체 복사'라고도 말한다.

 

 

얕은 복사가 아닌 서로 다른 객체를 만들고 싶다면 깊은 복사를 하면 된다.

 

1. 객체의 모든 프로퍼티를 순회하면서 복제할 객체에 추가

for (let key in obj) {
  clone[key] = obj[key];
}

2. Object.assign 함수 사용

Object.assign(clone, [obj1, obj2, obj3...])

obj1 ~ 3 의 프로퍼티들을 clone객체에 추가

기존 객체에 복제할 프로퍼티가 이미 존재한다면 값이 변경됨

 

3. slice 함수 사용

 

4.spread operator (전개 연산자) 사용

let clone = {...obj}

 

위의 4가지 방법은 depth가 1일 때만 가능하다. 즉 객체안에 객체가 선언이 되어있거나 2차원배열 이상이라면 해당 프로퍼티는 깊은 복사가 아닌 얕은 복사가 된다.

-> 배열의 실제 값들은 힙에 저장이 된다. 이때 depth가2인 [1,2,3 [4,5]]로 구성된 배열은 [1,2,3,주소값] 이렇게 힙에 저장되어있기 때문에 depth가2인 배열을 복사한다면 [1,2,3,주소값]을 복사하는것과 같다.

 

# 깊은복사

1. 재귀적으로 해결 

function cloneObject(obj) {
  var clone = {};
  for (var key in obj) {
    if (typeof obj[key] == "object" && obj[key] != null) {
      clone[key] = cloneObject(obj[key]);
    } 
    else {
      clone[key] = obj[key];
    }
  }

  return clone;
}

let obj  = {
  name: "k",
  subobj : {
    age : "10"
  }
};

let clone = cloneObject(obj);

console.log(obj);
console.log(clone);

console.log(obj===clone); //false
console.log(obj.subobj === clone.subobj); //flase

2. lodash 라이브러리 사용 

let clone = _.cloneDeep(obj);

 

 

# 기타 객체관련 함수

object.Keys(obj) : 객체의 프로퍼티를 배열로 반환함.

if 문에도 key in obj 형태로 사용이가능

hasOwnProperty()

for let key in obj

 

얕은 복사 : 객체를 새로운 변수에 할당 했을 때 객체의 값들이 복사가 되는게 아닌 객체의 주소값이 할당이 되는 복사. 따라서 복사한 변수의 값을 바꾸면 원래 객체의 값도 바뀐다. 참조에 의한 객체 복사라고도 한다.
깊은 복사 : 얕은 복사와 달리 주소값이아닌 값 자체를 복사하는 것. 

'WEB > Javascript' 카테고리의 다른 글

[JavaScript] 배열, 객체  (0) 2022.07.14
[JavaScript] 호이스팅(Hoisting)  (0) 2022.07.13
[JavaScript] 블록 스코프 vs 함수 스코프  (0) 2022.07.13
[JavaScript] 클로져  (0) 2022.07.12
[Javascript] 원시자료형, 참조자료형  (0) 2022.06.24