메모리 영역에는 '변수 영역'과 '데이터 영역'이 있다.
여기서 '데이터 영역'에 기록된 데이터는 불변값이므로 변하지 않는다.
아래와 같은 변수를 선언했다면
let a = 'abc';
< 변수 영역 >
이름 : a
값 : @1001
< 데이터 영역 >
주소 1001 : 'abc'
아래와 같이 변수 a의 값을 변경한다면
a = 'abcd';
< 변수 영역 >
이름 : a
값 : @1002
< 데이터 영역 >
주소 1001 : 'abc'
주소 1002 : 'abcd'
기존 데이터 영역에 있던 값이 변경되는 것이 아니라 새로운 값을 저장하여 해당하는 주소를 할당시킨다.
이러한 개념으로 모든 데이터는 '불변값'이다. 또한 기본형 데이터라고 해도 주소를 참조한다.
그렇다면 참조형 데이터는 어떨까?
let obj = {
a: 1,
b: 'test'
};
< 변수 영역 >
이름 : obj
값 : @1001
< 데이터 영역 >
주소 1001 : @2001 ~ ?
주소 1002 : 1
주소 1003 : 'test'
< 객체 1001의 변수 영역 >
주소 2001 - 이름 : a, 값 : @1002
주소 2002 - 이름 : b, 값 : @1003
기본형 데이터와 차이를 본다면 데이터 영역에 값이 바로 들어가는 것이 아닌
별도의 변수 영역의 주소가 들어간다는 점.
'변수 영역 -> 데이터 영역 -> 변수 영역 -> 데이터 영역' 루트로 기본형에 비해 한 번 더 거친다고 보면된다.
여기서 만약 복사를 한다면 어떻게 될까?
기본형 데이터의 복사 후 수정
let a = 'abc';
let b = a;
b = 'abcd';
// a === b (false)
< 변수 영역 >
이름 : a
값 : @1001
이름 : b
값 : @1001
< 데이터 영역 >
주소 1001 : 'abc'
에서
< 변수 영역 >
이름 : a
값 : @1001
이름 : b
값 : @1002
< 데이터 영역 >
주소 1001 : 'abc'
주소 1002 : 'abcd'
로 변경된다.
내가 변경하고자 했던 b만 변경되고 a는 변경되지 않았으니 별 문제 없다.
참조형 데이터의 복사 후 수정
let obj = {
a: 1,
b: 'test'
};
let obj2 = obj;
obj2.a = 2;
//obj.a === obj2.a (true)
< 변수 영역 >
이름 : obj
값 : @1001
이름: obj2
값 : @1001
< 데이터 영역 >
주소 1001 : @2001 ~ ?
주소 1002 : 1
주소 1003 : 'test'
< 객체 1001의 변수 영역 >
주소 2001 - 이름 : a, 값 : @1002
주소 2002 - 이름 : b, 값 : @1003
에서
< 변수 영역 >
이름 : obj
값 : @1001
이름: obj2
값 : @1001
< 데이터 영역 >
주소 1001 : @2001 ~ ?
주소 1002 : 1
주소 1003 : 'test'
주소 1004 : 2
< 객체 1001의 변수 영역 >
주소 2001 - 이름 : a, 값 : @1004
주소 2002 - 이름 : b, 값 : @1003
데이터 영역 1004번에 2가 새로 할당되고
객체 1001의 a 프로퍼티의 값만 변경된다.
결과적으로 obj와 obj2 모두 1001 객체를 참조하기 때문에,
변경하고 싶지 않았던 obj 도 같이 변경되는 결과가 발생한다.