- 자바스크립트에서 데이터 타입에는 아래와 같이 원시형과 참조형으로 나뉩니다.
- 자바스크립트 메모리 구조는 스택 메모리(정적 할당, 변수, 원시형 데이터 저장)와 힙 메모리(동적 할당, 참조형 데이터, 저장) 영역으로 나뉘어 있습니다.
원시형(Primitive Type)
객체를 제외한 모든 타입은 원시 값(불변 값)으로 값을 그대로 할당합니다.
- boolen
- null
- undefined
- number
- string
- symbol (ES6)
아래와 같이 newName에 name을 할당하고 다시 "jennie"로 값을 재할당 한 후 name과 newName을 확인해 보면 데이터의 불변성(newName의 값을 재할당 해도 name의 값이 변하지 않음)을 확인할 수 있습니다.
1
2
3
4
5
let name = "sara";
let newName = name;
newName = "jennie";
console.log(name, newName); // sara, jennie
이렇게 값이 변하지 않는 것 이 당연해 보이지만 그 이유는 아래와 같습니다.
1. 메모리(1002)에 식별자 name을 저장합니다.
| … | 1002 | … |
|---|---|---|
| 이름: name 값: |
2. "sara"를 비어있는 다른 메모리(5003) 공간에 저장합니다.
| … | 1002 | … |
|---|---|---|
| 이름: name 값: |
| … | 5003 | .. |
|---|---|---|
| “sara” |
3. name과 newName 은 같은 string 타입의 "sara"를 저장한 메모리(5003) 주소를 참조하게 됩니다.
| … | 1002 | 1003 |
|---|---|---|
| 이름: name 값: @5003 | 이름: newName 값: @5003 |
| … | 5003 | .. |
|---|---|---|
| “sara” |
4. newName에 "jennie"를 재할당 하면 string 타입의 "jennie"를 메모리(5004)에 저장하고 newName은 해당 주소(5004)를 참조합니다.
| … | 1002 | 1003 |
|---|---|---|
| 이름: name 값: @5003 | 이름: newName 값: @5004 |
| … | 5003 | 5004 |
|---|---|---|
| “sara” | “jennie” |
이와 같이 원시형에서는 데이터를 변경할 때 가리키는 주소를 직접 바꿔놓게 되기 때문에 불변성을 유지할 수 있습니다.
참조형(Reference Type)
객체 타입의 데이터로 값이 저장된 주소 값을 참조합니다.
- Object
- Array
- Function
- RegExp(정규 표현식)
- Set (ES6)
- Map (ES6)
같은 주소 값을 참조한다는 것은 얕은 복사(shallow copy)를 확인하면 이해할 수 있습니다.
아래와 같이 obj2.b 값을 재할당했을 때 obj.b의 값도 변경된 경우를 얕은 복사라고 합니다.
1
2
3
4
5
6
7
8
9
10
const obj = {
a: 1,
b: 2,
};
const obj2 = obj;
obj2.b = 3;
console.log(obj, obj2); // {a: 1, b: 3}, {a: 1, b: 3}
이렇게 obj의 값이 같이 변경된 이유는 아래와 같습니다.
1. obj를 메모리(1002)에 선언합니다.
| … | 1002 | 1003 |
|---|---|---|
| 이름: obj 값: @5002 | 이름: obj2 값: @1002 |
2. 메모리 구조 공간 하나에는 값이 하나씩밖에 못 들어가기 때문에 메모리(7103~) 공간을 확보합니다.
| 5002 | 5003 | 5004 | 5005 |
|---|---|---|---|
| @7103~ | 1 | 2 | 3 |
확보한 공간 메모리(7103 ~)에 프로퍼티(5003, 5004)를 하나씩 할당합니다.
| 7103 | 7104 | … |
|---|---|---|
| 이름: a 값: @5003 | 이름: b 값: @5004 -> @5005(3으로 재할당) |
3. obj2에 obj를 할당했으므로 obj는 1002를 참조합니다.
4. obj2.b 에 3으로 재할당(5005) 하는 경우 obj와 obj2는 같은 메모리(5002) 주소 값을 참조합니다.
이와 같이 얕은 복사는 obj2는 새로운 객체를 만든 것이 아니라 obj와 같은 주소 값을 참조하므로 obj2.b를 변경했지만 obj도 같이 변하는 것을 확인할 수 있습니다.
참고 - 코어 자바스크립트