View
이 장을 읽으면서 가장 헷갈렸던 부분인 불변값, 불변객체, 복사에 대한 부분만 정리하겠습니다.
데이터 할당
자바스크립트 엔진은 데이터를 변수 영역과 데이터 영역, 두 부분에 할당합니다.
각각의 영역은 주소값과 데이터값을 가지는데,
변수 영역의 데이터값은 이름(변수명)과 값(데이터영역의 주소값)을 가지게 되고
데이터 영역의 데이터값은 'abc' 같은 실 데이터가 들어가게 됩니다.
이러한 데이터 할당은 데이터 변환을 자유롭게 할 수 있게 하고, 메모리를 효율적으로 관리할 수 있게 해 줍니다.
만약 a라는 변수에 5004번의 데이터가 할당되어 있는데, 이 값을 변경하고 싶다고 합시다.
자바스크립트는 5004번에 해당하는 데이터 자체를 바꾸려면 데이터 영역의 메모리를 늘리거나 줄이는 일을 해야 합니다. 이는 다른 값들에게도 영향을 줄 수 있겠죠.
하지만 우리가 변경할 값을 데이터 영역의 5005번에 새로 생성하고, a라는 변수의 데이터값을 5005번으로 바꾸게 된다면 쉽게 해결됩니다.
이런 방식은 데이터를 중복 생성하는 걸 막을 수도 있습니다. 만약 5004번의 데이터를 b라는 변수에서 할당하고 싶다면 새로운 데이터를 만들지 않고, 5004번으로 연결하면 되기 때문입니다.
불변값
불변성 여부를 구분할 때의 변경 가능성의 대상은 데이터 영역입니다.
앞서 말했듯 데이터를 변경하려면 자바스크립트는 데이터 영역에 새로운 값을 새로 생성하고, 변수의 데이터값인 주소값을 그 새로운 데이터의 주소값으로 변경한다고 했습니다.
var a = 'abc';
a = a + 'def';
이 경우가 그러합니다. 'abc'라는 데이터 영역의 값에 'def'를 붙이는 게 아니라, 'abcdef'라는 새로운 데이터를 만들어 변수 a에 저장하는 것입니다.
따라서 이러한 문자열을 비롯한 기본형 데이터인 숫자, boolean, null, undefinde, Symbol은 모두 불변값입니다.
참조형 데이터를 변수에 할당하는 과정
기본형 데이터와의 차이는 객체의 변수 영역이 별도로 존재합니다.
var obj = {
a: 1,
b: 'bbb',
};
obj1.a = 2;
주소 | 1001 | 1002 | 1003 | 1004 | 1005 | ... |
데이터 | 이름: obj1 값: @5001 |
|||||
주소 | 5001 | 5002 | 5003 | 5004 | 5005 | |
데이터 | @7103 ~ ? | 1 | 'bbb' |
주소 | 7103 | 7104 | 7105 | 7106 | 7107 | ... |
데이터 | 이름: a 값: @5003 |
이름: b 값: @5004 |
이처럼 a 프로퍼티에 숫자 2를 할당하려는 경우, 데이터 영역에서 숫자 2를 검색합니다. 검색 결과가 없으므로 데이터 영역의 빈공간(@5005)에 저장합니다. 그리고 이 주소를 7103에 저장하겠죠.
주소 | 1001 | 1002 | 1003 | 1004 | 1005 | ... |
데이터 | 이름: obj1 값: @5001 |
|||||
주소 | 5001 | 5002 | 5003 | 5004 | 5005 | |
데이터 | @7103 ~ ? | 1 | 'bbb' | 2 |
주소 | 7103 | 7104 | 7105 | 7106 | 7107 | ... |
데이터 | 이름: a 값: @5005 |
이름: b 값: @5004 |
결국 변수 obj1이 가지고 있는 주소는 계속 @5001입니다. 새로운 객체가 만들어진 것이 아니라 기존의 객체 내부만 바뀐 것입니다.
기본형 데이터와 참조형 데이터의 변수 복사 비교
var a = 10;
var b = a;
var obj1 = {c: 10, d: 'ddd'};
var obj2 = obj1;
주소 | 1001 | 1002 | 1003 | 1004 | ... |
데이터 | 이름: a 값: @5001 |
이름: b 값: @5001 |
이름: obj1 값: @5002 |
이름: obj2 값: @5002 |
|
주소 | 5001 | 5002 | 5003 | 5004 | |
데이터 | 10 | @7103 ~ ? | 'ddd' |
주소 | 7103 | 7104 | ... |
데이터 | 이름: c 값: @5001 |
이름: d 값: @5003 |
기본적인 할당 자체는 @1002, @1002 모두 @5001을 가리키고, @1003, @1004 모두 @5002를 가리킨다는 점에서 동일합니다.
하지만 데이터를 변경시켜 보면 차이를 알 수 있습니다. 기본형 데이터를 복사한 변수 b의 값을 바꾼다면 변수가 가리키는 주소값이 바뀌어 @1001과 @1002가 가리키는 값이 달라지게 되겠죠.
그러나 참조형 데이터를 복사한 변수 obj2의 프로퍼티 c의 값을 20으로 바꾼다면, @7013이 가리키는 주소값이 달라질 뿐, 여전히 둘 다 @7103을 가리키고 있는 것은 동일하므로 둘은 여전히 같은 객체일 것입니다.
얕은 복사와 깊은 복사
얕은 복사는 바로 아래 단계의 값만 복사하는 방법입니다. 즉, 중첩된 객체에서 저장된 프로퍼티를 복사할 때 주솟값만 복사한다는 의미입니다. 이렇게 되면 원본과 사본이 동일한 참조형 데이터의 주소를 가리키게 되므로 앞서 말했던 것처럼 원본이 바뀌면 사본이 바뀌는 가변성을 띄게 됩니다.
하지만 우리는 객체를 사용할 때에도 불변성을 가지고 싶을 때가 있습니다. 모든 값을 복사해서 완전히 새로운 데이터를 만들고 싶을 때, 사본을 바꿔도 원본이 바뀌지 않으면 할 때 깊은 복사를 사용해야 합니다.
깊은 복사는 재귀적으로 내부의 프로퍼티들을 계속해서 복사하는 것입니다.
'Level-Up > 독서' 카테고리의 다른 글
[코어 자바스크립트] 05. 클로저 (0) | 2022.04.05 |
---|---|
[코어 자바스크립트] 04. 콜백 함수 (0) | 2022.03.25 |
[코어 자바스크립트] 3장. this (0) | 2022.03.11 |
[코어 자바스크립트] 2장. 실행 컨텍스트 (2) | 2022.02.25 |