자바스크립트에서는 모든 데이터를 원시 타입 또는 객체 타입으로 나누는데 그 중 원시 타입에는
- number
- string
- boolean
- undefined
- null
- symbol
위와 같은 타입들이 속한다.
원시 타입의 값은 불변성, 즉 immutable 하고 읽기 전용이라는 특징인데, 여기서 의문이 생길 수 있다.
var num = 123;
console.log(num); // 123 출력
num = 456;
console.log(num); // 456 출력
다음과 같은 코드에서 원시 타입, number 타입인 변수 num의 값이 바뀐거 아닌가? 🧐 라고 생각할 수도 있지만 여기서 바뀐건 123, 456 같은 '값' 자체가 아니라 number type '변수'가 가리키고 있는 값이다.
먼저 변수와 값이 차이를 알아보자.
✏️ 변수: 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 / 메모리 공간을 식별하기 위해 붙인 이름
✏️ 값: 변수에 저장된 데이터 / 표현식이 평가되어 생성된 결과
이 그림을 보면 더 잘 이해할 수 있는데, 우선 score라는 변수를 선언하면 자바스크립트 엔진이 undefined로 초기화 한다. 즉 score 변수가 undefined 라는 값이 저장된 변수를 가리킨다. 그리고 score에 값 80을 할당하면, 변수 score는 80 이라는 값이 저장된 메모리 공간을 가리킨다. 마찬가지로 변수 score에 90을 재할당하면 score는 이제 90 이라는 값이 저장된 메모리 공간을 가리킴으로써 재할당된다.
✓ 결론적으로 변경 불가능하다는 것은 '값'이다!
변수는 단지 재할당을 통해 저장하고 있는 값을 교체할 뿐이다.
이런 방식을 통해 자바스크립트는 데이터의 신뢰성을 보장할 수 있다.
앞서 원시 타입 변수는 단지 '값'을 저장할 뿐이고 '값' 자체는 immutable 하다는 것을 알아 보았다.
그리고 재할당을 통해 저장하는 값을 바꿀 수 있는데 그렇다면 다른 변수에 복사할 때는 어떨까?
원시 타입은 pass by value 라는 방식을 사용한다.
var score = 80;
var copy = score;
변수 copy에 score의 값을 복사해서 할당하는 과정이다.
pass by value, 값에 의한 전달 이라는 말처럼 copy에는 score가 저장하고 있던 '값' 80이 복사되어 저장된다.
✏️ 그림처럼 score와 copy는 각기 다른 메모리 공간을 가리키지만, 그 메모리 공간에는 모두 80이라는 값이 저장되어 있는 것이다.
💭 엄밀히 말하자면 pass by value도 사실은 메모리 주소를 전달하고 있다. 변수와 같은 식별자는 메모리 공간의 주소를 기억하고 그 주소로 값에 접근하기 때문이다.
원시 타입을 제외한 나머지 모든 데이터 타입은 객체 타입에 속하는데, 여기에는
- 객체
- 함수
- 배열
등이 있다.
원시 타입과 반대로 바뀔 수 있는 값, mutable 한 타입이 객체 타입이다.
그리고 가변적이라는 것은 프로퍼티, 즉 저장하는 값이 정해져 있지 않다는 말이다.
이렇게 되면 메모리 크기를 사전에 정해둘 수 없다. 그래서 객체 타입은 원시 타입과 다르게 '값'을 저장하지 않고 '메모리 주소'를 저장한다.
const person = {
name: 'Kia',
address: 'Seoul'
};
위 코드처럼 person이라는 객체를 선언했을 때, 객체 타입 person은 실제 값들이 저장되어 있는 메모리의 주소를 저장하고 있다. 그리고 값에 접근해야 할 필요가 생기면 저장하던 메모리 주소를 통해 참조 값(reference value)에 접근할 수 있다.
따라서 값이 아니라 메모리 주소를 저장하고 전달하는 객체 타입의 이런 방식을 pass by reference라고 부른다.
단점은
앞서 살펴본 두 방식의 공통점은
식별자가 기억하는 메모리 공간에 저장되어 있는 값을 복사해서 전달한다는 것이다. 그리고 pass by value 방식 또한 pass by reference와 같이 '값이 저장된 메모리 주소'를 전달한다.
✏️ 따라서 엄밀히 따지면 javascript에서는 '참조에 의한 전달'은 존재하지 않는다. '값에 의한 전달'만 존재할 뿐. 그러나 원시 타입과 객체 타입이 값을 저장하고 다루는 방식에는 차이가 있기에 이런 식으로 구분해서 부르고 있다.
참고: 모던 자바스크립트 Deep Dive 11장