#이 내용은 코어자바스크립트(by. 정재남)의 강의내용과 책을 정리한 내용입니다.
원래 목표는 매일 공부하고 블로그를 쓰는 것이었지만.. 단 하루만에 실패할 줄은 정말 몰랐다.. 이제라도 열심히 적을 예정이다!!
참조형 data type
앞서 말했듯 참조형 데이터 타입에는 Object(Array, Function, Date, RegExp, Map/WeakMap, Set/WeakSet)이 있다.
기본형은 주솟값을 바로 복제하는 반면
참조형은 값이 담긴 주솟값들로 이루어진 묶음을 가리키는 주솟값을 복제
한다는 점이 다르다.
아래에서 이 말이 무엇을 의미하는지 알아보자.
변수와 참조형 data type은 어떻게 메모리에 저장될까?
이전 글과 같이 실제 메모리 구조는 복잡하지만 이해를 위해 책에서 사용한 것과 비슷하게 간략하게 표현합니다.
var obj1 = {
a : 10,
b : [10,20]
};
우선 변수 영역에 빈 공간을 확보하고 식별자를 'obj1'으로 설정한다.
이해를 돕기 위해 @1002~ 는 변수영역, @3002~ 는 데이터 영역, @5002~ 는 obj1 의 프로퍼티 영역, @7002~ 는 obj1의 b의 프로퍼티 영역입니다.
주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
---|---|---|---|---|---|---|
데이터 | 식별자 : obj1 값 : |
주소 | ... | 3002 | 3003 | 3004 | 3005 | ... |
---|---|---|---|---|---|---|
데이터 |
주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
---|---|---|---|---|---|---|
데이터 |
주소 | ... | 7002 | 7003 | 7004 | 7005 | ... |
---|---|---|---|---|---|---|
데이터 |
데이터가 여러 개이다 보니 이들을 저장하기 위한 별도의 영역(@5002~)을 마련하고 이 영역의 주소를 @3002에 저장하고 @1002의 값에 @3002 주소를 저장한다.
주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
---|---|---|---|---|---|---|
데이터 | 식별자 : obj1 값 : @3002 |
주소 | ... | 3002 | 3003 | 3004 | 3005 | ... |
---|---|---|---|---|---|---|
데이터 | @5002 ~ |
주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
---|---|---|---|---|---|---|
데이터 |
주소 | ... | 7002 | 7003 | 7004 | 7005 | ... |
---|---|---|---|---|---|---|
데이터 |
객체 obj1.a의 값인 10을 데이터영역에서 검색 후 없으니 추가합니다. 이후 @5002의 식별자를 a로 설정하고 값은 10을 저장한 @3003을 저장합니다.
주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
---|---|---|---|---|---|---|
데이터 | 식별자 : obj1 값 : @3002 |
주소 | ... | 3002 | 3003 | 3004 | 3005 | ... |
---|---|---|---|---|---|---|
데이터 | @5002 ~ | 10 |
주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
---|---|---|---|---|---|---|
데이터 | 식별자 : a 값 : @3003 |
주소 | ... | 7002 | 7003 | 7004 | 7005 | ... |
---|---|---|---|---|---|---|
데이터 |
객체 obj.b의 값을 저장하려 보니 프로퍼티가 여러개이니 앞서 2번 단계처럼 이를 위한 별도의 영역(@7002~)을 마련합니다. 이후 이 주소를 데이터 영역(@3004)에 저장합니다. @5003에는 식별자 b, 값은 앞서 저장한 @3004를 저장합니다.
주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
---|---|---|---|---|---|---|
데이터 | 식별자 : obj1 값 : @3002 |
주소 | ... | 3002 | 3003 | 3004 | 3005 | ... |
---|---|---|---|---|---|---|
데이터 | @5002 ~ | 10 | @7002 ~ |
주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
---|---|---|---|---|---|---|
데이터 | 식별자 : a 값 : @3003 | 식별자 : b 값 : @3004 |
주소 | ... | 7002 | 7003 | 7004 | 7005 | ... |
---|---|---|---|---|---|---|
데이터 |
obj.b의 각 프로퍼티 들의 값을 데이터 영역에 저장하고 @7002 ~ 의 영역에 식별자와 함께 저장합니다.
주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
---|---|---|---|---|---|---|
데이터 | 식별자 : obj1 값 : @3002 |
주소 | ... | 3002 | 3003 | 3004 | 3005 | ... |
---|---|---|---|---|---|---|
데이터 | @5002 ~ | 10 | @7002 ~ | 20 |
주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
---|---|---|---|---|---|---|
데이터 | 식별자 : a 값 : @3003 | 식별자 : b 값 : @3004 |
주소 | ... | 7002 | 7003 | 7004 | 7005 | ... |
---|---|---|---|---|---|---|
데이터 | 식별자 : 0 값 : @3003 | 식별자 : 1 값 : @3005 |
여기서 obj1.a와 obj1.b[0]의 값은 둘 다 같은 10입니다. 위에 간략하게 표현한 메모 상에서도 같은 @3003을 가리키고 있습니다.
만약 같은 값이라고 한다면 데이터 영역에 새로 추가하지 않고 있는 것을 사용한다는 것을 알 수 있습니다. 즉 데이터를 추가할 때 데이터 영역에 해당하는 값이 있는지 검색하는 과정이 필요합니다.
언뜻 보면 비효율적이라고 생각할 수 있지만 메모리의 수명과 용량 등등을 고려하면 새로 저장할 때에는 비효율적일 수 있지만 이득이 훨씬 크다는 것을 알 수 있습니다.
그럼 추후에 값을 변경할 때는 어떻게 될까?
단순히 값을 변경하는 경우는 이전 글인 기본형 data type이 변하는 과정과 비슷하다. 다만 가장 큰 차이점이 있다.
var obj1 = {
a : 10,
b : [10,20]
};
obj1.a = 20;
obj1.b = 10;
obj1.a = 20;
이 부분부터 보면
데이터 영역에 20이 있으므로 obj1.a(@5002)의 값을 @3005로 바꿔주면 끝난다.
주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
---|---|---|---|---|---|---|
데이터 | 식별자 : obj1 값 : @3002 |
주소 | ... | 3002 | 3003 | 3004 | 3005 | ... |
---|---|---|---|---|---|---|
데이터 | @5002 ~ | 10 | @7002 ~ | 20 |
주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
---|---|---|---|---|---|---|
데이터 | 식별자 : a 값 : @3005 | 식별자 : b 값 : @3004 |
주소 | ... | 7002 | 7003 | 7004 | 7005 | ... |
---|---|---|---|---|---|---|
데이터 | 식별자 : 0 값 : @3003 | 식별자 : 1 값 : @3005 |
그럼 그 다음 부분은?
obj1.b = 10;
obj1.b(@5003)의 값을 @3003으로 저장해주면 된다.
주소 | ... | 1002 | 1003 | 1004 | 1005 | ... |
---|---|---|---|---|---|---|
데이터 | 식별자 : obj1 값 : @3002 |
주소 | ... | 3002 | 3003 | 3004 | 3005 | ... |
---|---|---|---|---|---|---|
데이터 | @5002 ~ | 10 | @7002 ~ | 20 |
주소 | ... | 5002 | 5003 | 5004 | 5005 | ... |
---|---|---|---|---|---|---|
데이터 | 식별자 : a 값 : @3005 | 식별자 : b 값 : @3003 |
주소 | ... | 7002 | 7003 | 7004 | 7005 | ... |
---|---|---|---|---|---|---|
데이터 | 식별자 : 0 값 : @3003 | 식별자 : 1 값 : @3005 |
이 경우 @3004를 참조하는 것은 아무것도 없다. 즉 참조 카운트가 0이 되고 @3004가 참조하는 @7002 ~ 또한 참조 카운트가 0이 된다. 이는 나중에 GC(garbage collector)의 대상이 된다.