원시 타입과 객체 타입은 크게 세 가지 측면에서 다르다.
원시 타입의 값, 즉 원시 값은 변경 불가능한 값(immutable value)이다. 이에 비해 객체(참조) 타입의 값, 즉 객체는 변경 가능한 값(mutable value)이다.
원시 값을 변수에 할당하면 변수(확보된 메모리 공간)에는 실제 값이 저장된다. 이에 비해 객체를 변수에 할당하면 변수(확보된 메모리 공간)에는 참조 값이 저장된다.
원시 값을 갖는 변수를 다른 변수에 할당하면 원본의 원시 값이 복사되어 전달된다. 이를 값에 의한 전달(pass by value)이라 한다. 이에 비해 객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달된다. 이를 참조에 의한 전달(pass by reference)이라한다.
원시 타입(primitive type)의 값, 즉 원시 값은 변경 불가능한 값(immutable value)이다.
상수와 변경 불가능한 값을 동일시하면 안된다. 상수는 재할당이 금지된 변수일 뿐이다.
원시 값을 할당한 변수에 새로운 원시 값을 재할당하면 원시 값을 변경하는 것이 아니라 새로운 메모리 공간을 확보하고 재할당한 원시 값을 저장한다는 것을 기억하자. (값이 아니라 변수, 메모리 공간이 변경된 것이다.)
변수가 참조하던 메모리 공간의 주소가 변경되는 이유는 변수에 할당된 원시 값이 변경 불가능한 값이기 때문이다.
문자열은 유사 배열 객체이면서 이터러블이므로 배열과 유사하게 각 문자에 접근할 수 있다.
유사 배열 객체란 마치 배열처럼 인덱스로 프로퍼티 값에 접근할 수 있고 length
프로퍼티를 갖는 객체를 말한다.
var str = 'string';
// 문자열은 유사 배열이므로 배열과 유사하게 인덱스를 사용해 각 문자에 접근할 수 있다.
console.log(str[0]); // s
// 원시 값인 문자열이 객체처럼 동작한다.
console.log(str.length); // 6
console.log(str.toUpperCase()); // STRING
원시 값을 객체처럼 사용하면 원시 값을 감싸는 래퍼 객체로 자동 변환된다.
var str = 'string';
// 문자열은 유사 배열이므로 배열과 유사하게 인덱스를 사용해 각 문자에 접근할 수 있다.
// 하지만 문자열은 원시 값이므로 변경할 수 없다. 이때 에러가 발생하지 않는다.
str[0] = 'S';
console.log(str);
var score = 80;
var copy = score;
console.log(score); // 80
console.log(copy); // 80
score = 100;
console.log(score); // 100
console.log(copy); // ?
변수에 원시 값을 갖는 변수를 할당하면 할당받는 변수(copy)에는 할당되는 변수(score)의 원시 값이 복사되어 전달된다. 이를 값에 의한 전달 이라 한다.
var score = 80;
// copy 변수에는 score 변수의 값 80이 복사되어 할당된다.
var copy = score;
console.log(score, copy); // 80 80
console.log(score === copy); // true
score, copy는 80으로 동일한 값을 갖지만 두 변수의 값은 다른 메모리 공간에 저장된 별개의 값이다.
지금까지 우리가 본 값에 의한 전달은 값을 복사하고 새로운 메모리 공간에 값을 바로 할당해주었지만 실제로 내부 동작은 다를 수도 있다. 파이썬에서는 재할당 전까지 같은 메모리 주소를 참조하다가 한 쪽에 재할당이 일어나면 그때서야 새로운 메모리 공간에 재할당된 값을 저장한다.
값에 의한 전달 이라는 용어는 ECMAScript 사양에는 등장하지 않는다. 엄격하게 표현하면 변수에는 값이 전달되는 것이 아니라 메모리 주소가 전달된다. 변수와 같은 식별자는 값이 아니라 메모리 주소를 기억하고 있기 때문이다.
식별자로 값을 구별해서 식별한다는 것은 식별자가 기억하고 있는 메모리 주소를 통해 메모리 공간에 저장된 값에 접근할 수 있다는 것을 의미한다. 즉, 식별자는 메모리 주소에 붙인 이름이라고 할 수 있다.
값에 의한 전달도 사실은 값을 전달하는 것이 아니라 메모리 주소를 전달한다. 단, 전달된 메모리 주소를 통해 메모리 공간에 접근하면 값을 참조할 수 있다.
결국 두 변수의 원시 값은 서로 다른 메모리 공간에 저장된 별개의 값이 되어 어느 한쪽에서 재할당을 통해 값을 변경하더라도 서로 간섭할 수 없다.
* 모던 자바스크립트 Deep Dive ( 자바스크립트의 기본 개념과 동작 원리 ) / 이웅모 지음