부리부리부리

[JS] 깊은 복사, 얕은 복사 본문

언어/JavaScript

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

부리부리부리부리 2021. 12. 21. 15:24

원시형 변수, 참조형 변수

변수 유형엔 대표적으로 원시형 변수(Primitive Type)와 참조형 변수(Reference Type)가 있다. 

 

원시형 변수

- 메모리 상에 고정된 크기로 저장되며 원시 데이터 값 자체를 보관하며 불변적이다.

- 기본적으로 하나의 메모리를 사용한다. (재사용) 

 

참조형 변수

- 메모리 상에 저장하는 공간이 있지만, 값을 보관하는게 아니고 주소를 보관한다. 

- 저장된 주소를 "참조" 하여 값을 불러온다. 

 

원시형 변수의 경우 깊은 복사, 얕은 복사를 고려할 필요가 없다. 메모리에 값 자체를 할당하기 때문이다.

하지만 참조형 변수의 경우는 다르다.  무슨 말인지 자세히 살펴보면,

var obj = {
    a : 1,
    b : 'b'
}

var obj2 = obj 

console.log(obj==obj2) // True

위 코드를 실행하면 obj2 는 obj을 "얕은 복사"한 객체이다. 

obj2.a = 10 ;
console.log(obj2) // { a: 10, b: 'b' }

console.log(obj) // { a: 10, b: 'b'}

분명 obj2객체 내에 a key의 value를 바꾸었는데, obj 또한 똑같이 10으로 바뀌었기 때문이다. 

 

W

 

 

처음 obj2 를 선언할 때, 메모리 내에서 obj와 obj2이 참조하는 주소는 @413과 @414로 다르다. 하지만 해당 주소로 가보면 각각 데이터 @1011 주소의 같은 값을 가져옴을 알 수 있다. (@1011 주소에 할당된 값 또한 객체)

 

var obj = {
    a : 1,
    b : 'b'
}

var obj2 = obj // obj가 참조하는 주소값을 복사! (@1011)

console.log(obj==obj2) // True

obj2.a = 10 ; // @1011의 객체 b가 참조하는 @1012로 가서 a의 값을 바꾼다.

console.log(obj2) // { a: 10, b: 'b' }

console.log(obj) // { a: 10, b: 'b'}  ==> obj 또한 @1011의 a 값 @1012를 참조하고 있기 때문에 같이 바뀐다.

 

HOW TO DEEP COPY

 

1. 참조 중인 주소값을 복사해오는게 (얕은 복사, shallow copy) 아니라 참조 중인 주소로 들어가서 해당 값을 직접 복사해오는 방식을 사용한다. 

let obj_1 = {
    'a': 1,
    'b': 2
}

let obj_2 = {};

for (let key in obj_1) {
    obj_2[key] = obj_1[key];
}

console.log(obj_1, obj_2) // { a: 1, b: 2 } { a: 1, b: 2 }


obj_1.a = 123

console.log(obj_1, obj_2) // { a: 123, b: 2 } { a: 1, b: 2 }

2. JSON stringfy를 사용한다. (매우 간단하지만 JSON 문법을 정확히 지켜주지 않으면 Syntax Error가 난다.)

let obj_1 = {
    'a': 1,
    'b': 2
}

temp = JSON.stringify(obj_1) // temp <== {"a":123,"b":2}

obj_2 = JSON.parse(temp) // obj_2 <== { a: 1, b: 2 }

obj_2.a = 123

console.log(obj_1,obj_2) // { a: 1, b: 2 } { a: 123, b: 2 }

 

객체 속에 또 객체가 들어가 있는 case에서 Deep Copy를 하려고 시도해보면 왜 2번 방법이 매우 간단하다고 하는지 알게 된다. 

 

'언어 > JavaScript' 카테고리의 다른 글

[JS] async/await/promise  (0) 2021.12.09