기본형, 참조형
자바스크립트의 데이터 타입에는 크게 두 가지,
기본형 데이터 타입(Primitive type),
참조형 데이터 타입(Reference type)이 있다.
불변값
JavaScript에서 모든 기본형 데이터 타입은 불변값이다.
한 번 만든 값은 바꿀 수 없고, 변경은 새로 만드는 동작을 통해서만 이뤄지는 것
을 불변값이라고 하는데 다음 예시를 살펴보자.
이 코드는 아래 표와 같이 저장된다.
var myString = 'abc';
주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
데이터 | 이름: myString 값: @5004 |
|||||
주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
데이터 | 'abc' |
이렇게 'def'를 기존 string에 추가한다면 어떻게 될까?
var myString = 'abc';
myString += 'def';
주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
데이터 | 이름: myString 값: @5005 |
|||||
주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
데이터 | 'abc' | 'abcdef' |
5004 주소의 데이터 값에 'def'가 추가되는 게 아니라 새로운 메모리에 새 문자열이 할당된다.
이것이 불변값의 특징이다.
이 때 기존 변수 myString의 데이터 값으로 새로운 메모리 주소 "@5005" 가 할당되는데
이는 @5004라는 값에서 @5005라는 값으로 재할당 된 것이다.
따라서 myString이 만약 const로 선언되었다면 위 연산이 불가능하다!
참조형 데이터 타입이 할당되는 모양
JavaScript에서 참조형 데이터 타입이 할당되는 모양은 다음과 같다.
myVariable은 Object 타입이므로 참조형 데이터 타입이다.
그 안의 a와 b 프로퍼티는 기본형 데이터 타입이다.
var myVariable = {
a: 1,
b: 'hi',
};
주소(변수 영역) | 1001 | 1002 | 1003 | 1004 | ... |
데이터(변수 영역) | 이름: myVariable 값: @5001 |
||||
주소(데이터 영역) | 5001 | 5002 | 5003 | 5004 | ... |
데이터(데이터 영역) | @7103 ~ ? | 1 | 'hi' |
주소(객체 @5001의 변수 영역) | 7103 | 7104 | 7105 | 7106 | ... |
데이터(객체 @5001의 변수 영역) | 이름: a 값: @5003 |
이름: b 값: @5004 |
불변 객체(immutable object)
사전적 의미로 변하지 않는 객체이다.
최근 React, Vue.js, Angular 등의 라이브러리에서 뿐만 아니라
함수형 프로그래밍, 디자인 패턴 등에서도 매우 중요한 기초가 되는 개념이라고 한다.
자바스크립트에서 불변객체라 함은 기본형 데이터 타입(Primitive type)을 말할 수 있겠다.
또 코어자바스크립트에서 말하는 불변 객체를 필자는 다음과 같이 이해하고 있다.
변수 a가 있다.
변수 a를 복사하여 변수 b에 담았다.
b를 수정할 때 a가 변화하면 a는 가변 객체
변화하지 않으면 a는 불변 객체
var myString = 'abc';
var yourString = myString;
주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
데이터 | 이름: myString 값: @5004 |
이름: yourString 값: @5004 |
||||
주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
데이터 | 'abc' |
var myString = 'abc';
var yourString = myString;
yourString += 'def';
// myString: 'abc';
// yourString: 'abcdef';
주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
데이터 | 이름: myString 값: @5004 |
이름: yourString 값: @5005 |
||||
주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
데이터 | 'abc' | 'abcdef' |
기본형 데이터 타입은 수정이 일어나면 새로운 데이터 영역의 메모리에 새로운 데이터가 생성되며
그 메모리 주소가 변수에 할당되기 때문에 불변 객체이다.
불변 객체를 만드는 방법으로서의 깊은 복사
기본형 데이터와 달리 참조형 데이터에는 두 가지 복사 방법이 있다.
얕은 복사와 깊은 복사가 그것이다.
얕은 복사는 연결된 메모리 주소 딱 한 번(한 단계 밑) 까지만 복사가 된다.
깊은 복사는 연결된 메모리 주소를 끝까지 쫓아가 복사한다.
만약 Object를 복사했는데, Object의 한 프로퍼티 안에 또 다른 참조형 데이터 타입이 들어있다면
거기서부터는 복사되지 않는다.
var myObj = {
a: 1,
b: {
'age': 19,
'name': '영자',
}
};
var yourObj = myObj;
위 상황에서 myObj의 b 프로퍼티와 yourObj의 b 프로퍼티는 완전히 동일한 객체가 할당 되어 있는 상태이다.
따라서 yourObj의 b 프로퍼티를 수정하면 myObj에도 변화가 생긴다.
myObj는 불변 객체가 아닌 것이다.
계속 복사해서 완전히 끝 기본형 데이터 타입에 도달할 때까지 복사를 한다면 myObj는 불변 객체가 된다.
복사가 이루어지면 중간의 프로퍼티를 완전히 새로운 메모리 주소에 할당하기 때문이다.
(깊은 복사)
(코어자바스크립트 책에선 깊은 복사의 방법으로 재귀적 코드와 JSONParser를 이용한 방법을 소개한다.)
주소 | 7103 | 7104 | ... | 주소 | 8204 | 8205 | ... |
데이터 | 이름: 'a' 값: @5001 |
이름: 'b' 값: @5003 |
데이터 | 이름: 'a' 값: @5001 |
이름: 'b' 값: @5003 |
얕은 복사를 한다면 복사가 안된 시점부터의 프로퍼티는 그냥 같은 주소의 동일한 값이 된다.
@7103 @7104 주소가 원본 객체, 복사본 둘 다에 할당 되어 있는 것이다.
깊은 복사를 한다면 복사된 객체를 변경해도 원본이 훼손되지 않는다.
"원본 객체"가 "불변 객체"가 되는 것이다.
'책 > 코어자바스크립트' 카테고리의 다른 글
05. 클로저와 debounce, 커링 (0) | 2022.03.15 |
---|---|
Async/ await (0) | 2022.03.12 |
콜백함수에서의 this (0) | 2022.03.12 |
[코어자바스크립트] 03. 종잡을 수 없는 this (0) | 2022.03.02 |