원시 타입(Primitive Type)
stack memory에 저장되는 데이터
값 자체로써 변수에 저장되고 복사 됩니다. (메모리 값 수정하지 않는 불변값)
- Number
- String
- Boolean
- null
- undefined
- Symbol
기본형의 메모리 할당
let a;
a = 'abc';
| 주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
|---|
| 데이터 | | 이름: a | | | | |
| | 값: @5004 | | | | |
| 주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
|---|
| 데이터 | | | | 'abc' | | |
재할당
let a;
a = 'abc';
a = 'abcdef';
| 주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
|---|
| 데이터 | | 이름: a | | | | |
| | 값: @5004 -> @5005 | | | | |
| 주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
|---|
| 데이터 | | | | 'abc' | 'abcdef' | |
a의 값을 바꾸면 값의 주소가 바뀜
같은 원시 값을 가진 두 변수 비교
let a = 'abc';
let b = 'abc';
console.log(a === b)
| 주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
|---|
| 데이터 | | 이름: a | 이름: b | | | |
| | 값: @5004 | 값: @5004 | | | |
| 주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
|---|
| 데이터 | | | | 'abc' | | |
깊은 복사
let a = 10;
let b = a;
console.log(a === b)
| 주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
|---|
| 데이터 | | 이름: a | 이름: b | | | |
| | 값: @5002 | 값: @5002 | | | |
| 주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
|---|
| 데이터 | | 10 | | | | |
재할당
let a = 10
let b = a
b = 15;
console.log(a === b)
| 주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
|---|
| 데이터 | | 이름: a | 이름: b | | | |
| | 값: @5002 | 값: @5002 -> @5003 | | | |
| 주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
|---|
| 데이터 | | 10 | 15 | | | |
참조 타입(Reference Type)
heap memory에 저장되는 데이터
stack memory에 주소를 저장하고 실제 객체와 함수는 heap memory에 저장합니다.
참조값을 통해 변수에 저장되고 복사 됩니다. (메모리 값 수정되는 가변값)
- Object
- Array
- Function
- RegExp
- Set/ WeakSet
- Map/ WeakSet
...
참조형의 메모리 할당
let obj = {
a: 1,
b: 'bbb'
};
console.log(obj);
| 주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
|---|
| 데이터 | | 이름: obj | | | | |
| | 값: @5002 | | | | |
| 주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
|---|
| 데이터 | | @7103 ~ ? | 1 | 'bbb' | | |
| 주소 | ... | 7002 | 7003 | 7004 | 7005 | ... |
|---|
| 데이터 | | | 이름: a | 이름: b | | |
| | | 값: @5003 | 값: @5004 | | |
재할당
let obj = {
a: 1,
b: 'bbb'
};
obj.a = 2;
console.log(obj);
| 주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
|---|
| 데이터 | | 이름: obj | | | | |
| | 값: @5002 | | | | |
| 주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
|---|
| 데이터 | | @7103 ~ ? | 1 | 'bbb' | 2 | |
| 주소 | ... | 7102 | 7103 | 7104 | 7105 | ... |
|---|
| 데이터 | | | 이름: a | 이름: b | | |
| | | 값: @5003 -> @5005 | 값: @5004 | | |
프로퍼티의 값이 바뀌어도 obj라는 값의 주소는 변하지 않음
중첩 객체의 메모리 할당
let obj = {
x: 3,
arr: [ 3, 4 ]
};
console.log(obj);
| 주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
|---|
| 데이터 | | 이름: obj | | | | |
| | 값: @5002 | | | | |
| 주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
|---|
| 데이터 | | @7103 ~ ? | 3 | @8104 ~ ? | 4 | |
| 주소 | ... | 7102 | 7103 | 7104 | 7105 | ... |
|---|
| 데이터 | | | 이름: x | 이름: arr | | |
| | | 값: @5003 | 값: @5004 | | |
| 주소 | ... | 8104 | 8105 | 8106 | 8107 | ... |
|---|
| 데이터 | | 이름: 0 | 이름: 1 | | | |
| | 값: @5003 | 값: @5005 | | | |
재할당
let obj = {
x: 3,
arr: [ 3, 4 ]
};
obj.arr = 'str';
console.log(obj);
| 주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
|---|
| 데이터 | | 이름: obj | | | | |
| | 값: @5002 | | | | |
| 주소 | ... | 5002 | 5003 | 5004 | 5005 | 5006 | ... |
|---|
| 데이터 | | @7103 ~ ? | 3 | @8104 ~ ? | 4 | 'str' | |
| 주소 | ... | 7102 | 7103 | 7104 | 7105 | ... |
|---|
| 데이터 | | | 이름: x | 이름: arr | | |
| | | 값: @5003 | 값: @5004 -> @5006 | | |
| 주소 | ... | 8104 | 8105 | 8106 | 8107 | ... |
|---|
| 데이터 | | 이름: 0 | 이름: 1 | | | |
| | 값: @5003 | 값: @5005 | | | |
@5004는 참조 카운트가 0이 되어 가비지 컬렉터로 인해 사라집니다.
같은 참조 값을 가진 두 변수 비교
let obj1 = {
c: 10,
};
let obj2 = {
c: 10
};
console.log(obj1 === obj2);
console.log(obj1.c === obj2.c);
| 주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
|---|
| 데이터 | | 이름: obj1 | 이름: obj2 | | | |
| | 값: @5002 | 값: @5003 | | | |
| 주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
|---|
| 데이터 | | @7103 | @7104 | 10 | | |
| 주소 | ... | 7102 | 7103 | 7104 | 7105 | ... |
|---|
| 데이터 | | | 이름: c | 이름: c | | |
| | | 값: @5004 | 값: @5004 | | |
obj1.c와 obj2.c는 메모리 상에서 서로 다른 위치에 저장된 값이 됩니다.
얕은 복사
let obj1 = {
c: 10,
d: 'ddd'
};
let obj2 = obj1
console.log(obj1 === obj2);
| 주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
|---|
| 데이터 | | 이름: obj1 | 이름: obj2 | | | |
| | 값: @5002 | 값: @5002 | | | |
| 주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
|---|
| 데이터 | | @7103 ~ ? | 10 | 'ddd' | | |
| 주소 | ... | 7102 | 7103 | 7104 | 7105 | ... |
|---|
| 데이터 | | | 이름: c | 이름: d | | |
| | | 값: @5003 | 값: @5004 | | |
재할당
let obj1 = {
c: 10,
d: 'ddd'
};
let obj2 = obj1
obj2.c = 20;
console.log(obj1 === obj2);
console.log(obj1)
| 주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
|---|
| 데이터 | | 이름: obj1 | 이름: obj2 | | | |
| | 값: @5002 | 값: @5002 | | | |
| 주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
|---|
| 데이터 | | @7103 ~ ? | 10 | 'ddd' | 20 | |
| 주소 | ... | 7102 | 7103 | 7104 | 7105 | ... |
|---|
| 데이터 | | | 이름: c | 이름: d | | |
| | | 값: @5003 -> @5005 | 값: @5004 | | |
객체를 복사하고 복사한 객체의 값을 바꾸었을 때 원본 객체의 값도 같이 바뀝니다.
이러한 이유 때문에 매번 새로운 객체를 만들거나 불변객체를 사용합니다.
참고