개요
자바스크립트 코드를 짜던 중 신기한 일이 발생했습니다.
다음 코드를 보고 console.log의 값을 맞춰보세요.
const A = 1;
const B = 1;
const C = {
num: 1
}
const D = {
num: 1
}
console.log(A === B);
console.log(C === D);
저는 두 번 모두 true가 나올 것이라고 생각했습니다.
하지만 결과는?
console.log(A === B); // true
console.log(C === D); // false
분명 C와 D에 같은 key value를 넣었음에도 false가 나왔습니다.
그 이유는 원시(Primitive) 타입과 객체(Object) 타입의 차이에 있습니다.
원시 타입 vs 객체 타입
1. 원시 타입 (Primitive)
설명
원시 타입이란 변경 불가능한(immutable) 값입니다.
JavaScript에서 제공하는 원시 타입은 다음과 같습니다.
- 숫자(Number): 정수와 실수를 포함합니다.
- 문자열(String): 텍스트 데이터를 나타냅니다.
- 불리언(Boolean): true 또는 false 값을 가집니다.
- null: 의도적으로 비어 있는 값.
- undefined: 값이 할당되지 않은 변수.
- 심볼(Symbol): 고유하고 변경 불가능한 값으로, 주로 객체 속성 키로 사용됩니다.
- BigInt: 큰 정수를 나타내기 위한 숫자 타입.
특징
- 변경 불가능: 원시 타입의 값은 변경할 수 없습니다. 예를 들어, 문자열을 변경하려면 새로운 문자열을 생성해야 합니다.
- 값 비교: 원시 타입은 값을 비교할 때 값 자체를 비교합니다.
예시
변경 불가능 하다는 말은 다음과 같습니다.
let str1 = "Hello";
let str2 = str1;
str2 = "World";
console.log(str1); // "Hello"
console.log(str2); // "World"
위 예시에서 `str1` 과 `str2` 는 처음에는 같은 값을 가지지만, `str2`를 변경해도 `str1`은 변경되지 않습니다.
2. 객체 타입 (Object)
설명
객체 타입은 변경 가능한(mutable) 데이터 구조를 가집니다.
JavaScript에서 객체 타입은 다음과 같은 종류가 있습니다:
- 객체(Object): 키-값 쌍의 집합입니다.
- 배열(Array): 순서가 있는 값의 리스트입니다.
- 함수(Function): 실행 가능한 코드 블록입니다.
- 날짜(Date): 날짜와 시간을 나타냅니다.
- RegExp: 정규 표현식을 나타냅니다.
- Map, Set: 고유한 키 또는 값을 저장하는 구조입니다.
특징
- 변경 가능: 객체 타입은 값을 변경할 수 있습니다. 객체의 속성을 추가, 삭제, 수정할 수 있습니다.
- 참조 비교: 객체 타입은 값을 비교할 때 참조(reference)를 비교합니다. 즉, 같은 객체를 참조하고 있는지 비교합니다.
예시
let obj1 = { name: "Alice" };
let obj2 = obj1;
obj2.name = "Bob";
console.log(obj1.name); // "Bob"
console.log(obj2.name); // "Bob"
위 예시에서 `obj1`과 `obj2`는 같은 객체를 참조하고 있기 때문에, `obj2`를 통해 객체의 속성을 변경하면 `obj1`에서도 변경된 값을 확인할 수 있습니다.
3. 원시 타입과 객체 타입의 차이점
- 변경 가능성
- 원시 타입: 변경 불가능(immutable)
- 객체 타입: 변경 가능(mutable)
- 저장 방식
- 원시 타입: 값 자체를 저장
- 객체 타입: 참조를 저장
- 비교 방식
- 원시 타입: 값 자체를 비교
- 객체 타입: 참조를 비교
- 메모리 할당
- 원시 타입: 고정된 크기의 메모리 할당
- 객체 타입: 동적으로 크기가 변하는 메모리 할당
4. 위 문제의 이유
원시 타입의 경우 A 에 1을 넣는다면 A라는 박스에 1을 담게 됩니다.
하지만 객체 타입의 경우 A에 { num: 1 }을 넣는 다면 A라는 박스에 "1234구역" 이라는 위치를 담고 "1234 구역"에 { num: 1 }이 존재하게 됩니다.
여기에서 문제가 발생합니다.
객체 타입을 비교할때는 어느 구역인지를 비교하기 때문에 "1234 구역"과 "4321 구역" 모두 { num: 1 } 이 있다 하더라도 서로 구역이 다르기 때문에 false가 나오게 되는 겁니다.
마치며..
해당 개념은 React의 useEffect, useMemo를 사용할 때 중요하므로 잘 알아두는 게 좋을 것 같습니다.
'Programming > JavaScript' 카테고리의 다른 글
[Node] NVM 설치와 사용 (Windows) (1) | 2024.07.22 |
---|---|
[JavaScript] 브라우저 밖 알림 기능 (0) | 2024.04.29 |
[JavaScript] forEach와 map의 차이점 (0) | 2024.04.23 |
[JavaScript] 한글 파일(.hwp) 양식에 맞춰 출력하기 (0) | 2024.04.19 |
[JavaScript] 최단 경로 찾기 A* 알고리즘 (0) | 2024.03.19 |