[JavaScript] 원시(primitive)타입 VS 객체(object)타입

2023-07-18

자바스크립트에서 제공하는 타입은 원시타입과 객체타입으로 나눌 수 있다.

  1. 원시타입: 숫자(number), 문자열(string), 불리언(boolean), undefined, null, 그리고 ES6에서 심벌(symbol)타입이 추가 되었다.
  2. 객체타입 : 배열, 객체, 함수 등
    위 두 가지 타입의 차이점에 대해 알아보자

1. 원시 값은 변경 불가능한 값이지만 객체(참조) 타입은 변경 가능한 값이다.

원시 타입은 값 자체의 변경이 불가능하다. 이를 불변성이라고 하는데, 그렇다면 아래와 같은 코드에서 헷갈릴 수 있다.

let a = 100;
console.log(a); // 100
a = 200;
console.log(a); // 200

변수의 a값이 변경되었으므로 값이 변경 가능한것이 아니냐고 할 수 있겠지만, 사실 변수 a에는 100과 200이 모두 저장되어 있다. 변수의 재할당을 통해 변수가 가르치는 값이 변경된 것 일 뿐 100의 값 자체가 수정된 것이 아니다. 즉 변수 a 에는 100과 200이 할당 되었고, a는 이 값을 모두 가지고 있으면서 마지막으로 재할당된 200이라는 값을 가르치고 있는 것일 뿐이다.

반대로 객체 타입은 값의 변경이 가능하다

const a = {};
a.o = 1;
console.log(a); // {a:1}

상수 const는 재할당을 할 수 없다. 하지만 const에 할당된 값은 객체 타입이므로 값 자체에 접근하여 값 변경이 가능하다. 즉 a라는 변수는 {} 라는 값에서 {a: 1} 로 변경되었다. 상수 a가 담고있는 값 자체가 변경된 것이다.

2. 변수에 할당된 원시값은 실제값이 저장되지만 변수에 할당된 객체값은 참조 값이 저장된다.

let a = 100;
let b = { name: `Kim`, age: 10 };

위의 코드는 아래와 같이 표현한다.

원시값을 할당한”변수 a는 100의 값을 “갖는다” 객체를 할당한 변수 b는 객체를 “참조하고 있다” 혹은 객체를 “가르키고 있다”

위와 같이 표현하는 이유는, 변수 a에는 100이라는 숫자 자체가 저장되지만 b는 값이 다른 장소에 저장되고 이 장소를 가르킨다. 따라서 변수 b에 접근할 경우, 저장된 위치의 값을 참조하여 보여준다.

3. 원시 값은 값에 의한 전달을 하며 객체 값은 참조에 의한 전달을 한다.

let a = 100;
let b = a;

console.log(a); // 100
console.log(b); // 100

console.log(a === b); //true

a = 200;

console.log(a); // 200
console.log(b); // 100
console.log(a === b); // false

변수에 변수를 할당했을때, 변수 a는 100이고 b는 a의 값 100을 복사하여 새로운 곳에 저장한다. 따라서 a의 값이 바뀌어도 변수 b의 값은 변하지 않는다. 원시 값은 값에 의한 전달을 하기 때문이다.

1.

let a = { name: `Kim`, age: 10 };
let b = a;

console.loo(a === b); // true
console.log(a); // { name: `Kim`, age: 10 };
console.log(b); // { name: `Kim`, age: 10 };

a = { name: `Lee`, age: 20 };
console.log(a === b); // true

consooe.log(a); // { name: `Lee`, age: 20};
console.log(b); // { name: `Lee`, age: 20};

객체는 참조에 의한 전달을 한다. 즉 변수에 변수를 할당했을때 변수 a는 값을 참조하여 가르치고 있고 변수 b도 같은 장소를 바라보며 가르친다(참조한다). 즉 객체타입은 여러 개의 식별자가 하나의 객체를 공유할 수 하기 때문에 변수 a의 값을 변경했을 경우 b도 그대로 영향을 받아 변경된 값을 가르키게 된다.

2.

let a = {name: `Lee`}

let b = a

console.log( a ==== b) // true
let c = { name: `Kim` };

let d = { name: `kim` };

console.log(c === b); // false

왜 비교연산자로 비교하였을때 a와 b는 같고, c와 d는 다를까? 이는 객체가 값을 참조하는 특성때문인데 변수에 변수를 할당하였을때 a와 b는 참조하고 있는 (가르치고 있는) 값이 같다.

하지만 c가 참조하고 있는 값과 d가 참조하고 있는 즉 가르치고 있는 장소는 다르기 때문에 비록 내용은 같지만 각 변수의 참조값은 전혀 다른 값이라고 할 수 있다.