Javascript의 변수 선언과 데이터 할당
자바스크립트의 변수 선언에 따라 데이터가 어떻게 할당되는지 알아보자.
var a = 'abc';
라는 구문이 있다. 이에 따른 메모리 할당을 봐보자.
주소 | … 1002 | 1003 | 1004 | 1005 | 변수영역 |
데이터 | 이름 :a 값 : @5004 |
변수영역 | |||
주소 | …5002 | 5003 | 5004 | 5005 | 데이터영역 |
데이터 | 'abc' | 데이터영역 |
변수영역과 데이터영역으로 공간이 분리되어 있고 변수영역에서 변수의 값은 데이터영역의 주소 값을 바라보고 있다.
이 변수 a의 값을 수정해보자.
a = 'abcde';
주소 | … 1002 | 1003 | 1004 | 1005 | 변수영역 |
데이터 | 이름 :a 값 : @5005 |
변수영역 | |||
주소 | …5002 | 5003 | 5004 | 5005 | 데이터영역 |
데이터 | 'abc' | 'abcde' | 데이터영역 |
변수영역의 메모리주소는 그대로지만 값의 주소가 바뀌었다.
데이터 영역에서 'abcde'라는 새로운 값의 메모리가 할당되었으며 그 주소 값을 변수영역에서 바라보는 것이다.
이 구조는 기본형 데이터타입으로 모두 불변의 값이다. 불변의 값은 데이터 영역에서 값이 정해져 있어서 바꾸려면 새로 메모리를 할당할 수 밖에 없다는 애기와 같다.
그렇다면 데이터영역에서 값이 변할 수 있을까?
이에 대한 답이 바로 참조형 데이터타입이다.
참조형 데이터타입은 가변값이다
데이터영역에서 값이 정해져 있는 것이 아니라, 데이터영역에서 값을 또 참조하는 것이다.
예를 들어 아래와 같이 obj1 이라는 객체가 있다.
var obj1 = {
a:1,
b:2
};
이 obj1이라는 변수는 어떻게 메모리가 할당되어 질까? 한번 알아보자.
==>
주소 | … 1002 | 1003 | 1004 | 1005 | 변수영역 |
데이터 | 이름 :obj1 값 : @5003 |
변수영역 | |||
주소 | …5002 | 5003 | 5004 | 5005 | 데이터영역 |
데이터 | @7103~? | 1 | 2 | 데이터영역 |
변수영역에 먼저 obj1의 메모리가 할당되고 기본형과 마찬가지로 값에 데이터영역의 주소 값이 들어간다. 하지만 여기서 주의 할 점이 데이터영역의 주소 값에서 다이렉트로 값이 들어간 것이 아니라 @7103~ 이라는 또 다른 메모리주소를 참조하고 있다.
주소 | 7103 | 7104 | 7105 | 7106 | 객체 @5003의 변수영역 |
데이터 | 이름 : a 값 : @5004 |
이름 :b 값 : @5005 |
객체 @5003의 변수영역 |
이렇게 객체 안에서 선언된 변수들이 또 객체의 변수영역으로 메모리가 할당되어지고 그 값에서 비로소 데이터영역의 실제 값을 바라보는 것이다.
그렇다면 이게 어떤 차이가 있고 무슨 상황을 만든다는 것인가?
이런 식으로 데이터를 복제해보자.
obj1안에 a의 값을 바꿧을 뿐인데, obj2 의 값도 바뀌었다.
왜 why?? 이 두 변수는 같은 메모리주소 값을 바라보고 있기 때문이다.
==>
주소 | 1002 | 1003 | 1004 | 1005 | 변수영역 |
데이터 | 이름:obj2 값 : @5003 |
이름 :obj1 값 : @5003 |
변수영역 | ||
주소 | 5002 | 5003 | 5004 | 5005 | 데이터영역 |
데이터 | 5 | @7103~? | 1 | 2 | 데이터영역 |
변수영역에 먼저 obj1의 메모리가 할당되고 기본형과 마찬가지로 값에 데이터영역의 주소 값이 들어간다. 하지만 여기서 주의 할 점이 데이터영역의 주소 값에서 다이렉트로 값이 들어간 것이 아니라 @7103~ 이라는 또 다른 메모리주소를 참조하고 있다.
주소 | 7103 | 7104 | 7105 | 7106 | 객체 @5003의 변수영역 |
데이터 | 이름 : a 값 : @5002 |
이름 :b 값 : @5005 |
객체 @5003의 변수영역 |
즉, obj1의 @5003의 값을 obj2도 같이 바라보고 있는 것이고, obj1의 a라는 변수를 고치면
마지막으로 실제 값을 참조하는 주소 @7103안에서 바라보고 있는 주소 값이 @5002로 바뀌는 것이며,
변수가 참조하고 있는 @5003이라는 주소 값은 변함이 없는 것이다.
따라서 obj1과 obj2는 같은 @5003을 바라보고 있기 때문에 하나의 변수 값만 바꿔도 둘 다 같이 바뀌게 되는 것이다.
이를 해결하려면 서로 다른 메모리 주소를 가지고 있는 객체를 만들어서 각각의 객체들을 복사해야된다.
다음과 같이 코드를 짜보자.
var copyObject = function(target){
var result = {};
for( var prop int target){
result[prop] = target[prop];
}
return result;
};
이렇게 객체의 메모리를 새로 생성해서 복사해야 그 안의 프로퍼티의 값을 바꿔도 각각의 객체만 바뀌게 된다.
이렇게 복사해야 프로퍼티의 값을 바꿔도 각각의 객체만 바뀐다.
이를 얕은 복사라고 하며, 객체안에 객체가 있을 경우 이 또한 값이 같이 바뀌기 때문에, 객체안에 객체가 있을 경우에는 깊을 복사로 객체를 복사해줘야 한다.
깊은 복사의 코드는 다음과 같다.
var copyObjectDeep = function (target) {
var result = {};
if (typeof target === 'object' && target !== null) {
for (var prop in target) {
result[prop] = copyObjectDeep(target[prop]);
}
} else { result = target; }
return result;
};
이렇게 자바스크립트의 변수 선언에 따라 데이터가 어떻게 할당되었는지 알아보았다. 끗.
댓글