본문 바로가기
JavaScript

[]===[], {}==={} 는 거짓(false)이다

by LeeJ1Hyun 2022. 12. 31.

 

let arr = [1, 2, 3];
let arr2 = [1, 2, 3];

console.log(arr === arr2); //false

 

완벽하게 일치하는 두 배열을 비교하면 Boolean 값은 false이다. 이는 자바스크립트 자료형의 특징 때문이다. 총 8가지의 데이터 타입은 원시 자료형(primitive type)과 참조 자료형(reference type) 2가지 특징으로 나뉜다.

 

JavaScript의 원시 자료형과 참조 자료형

원시 자료형은 선언될 때 변수에 값이 담기지만 참조 자료형은 주소(일명 reference)가 담긴다. string, number, boolean, undefined, null 등 이들은 "홍길동", 1, true와 같이 하나의 데이터만을 담는다. 반면 참조 자료형은 원시 자료형들의 집합이라고 볼 수 있다. array, object이 대표적인데 이들의 크기는 고정적이지 않다. 배열과 객체는 언제든 각각 요소, 속성이 추가될 수도 제거될 수도 있기 때문이다. 즉, 유동적으로 크기가 변하는 데이터들을 보관하기 위해서는 변수 자체가 아닌 다른 어딘가에 보관함을 만들어 저장하고 변수에는 그 주소(reference)를 대신 할당해야 한다.

 

값과 주소에 의해 데이터를 전달하는 것에 차이를 이해하기 위해서는 자바스크립트 엔진(V8)에 대한 지식이 필요하다. 특히 메모리에 대한 지식이 필요한데 Call Stack과 Heap으로 나뉜다. Call Stack에는 지역 변수를 저장하고 이 변수들은 LIFO 형태로 저장된다. 또한 원시 자료형들이 이곳에 저장된다.

 

let str = "JavaScript!!!";
str = "TypeScript!";
let num = 1000;
let kor = "안녕하세요";

그림처럼 Call Stack은 LIFO 즉, 나중에 들어온 것이 먼저 나가는 데이터 저장 형태를 띈다. 변수에 자료를 재할당 할 때는 순서에 영향이 없으며 기존 값은 사라지고 새로운 값이 그 자리에 들어가게 된다.

 

Heap 메모리에는 참조 자료형들이 할당되며 LIFO 형식이 아닌 마구잡이로 순서가 없다. 위에서 말한 것과 같이 데이터는 이 보관함에서 관리되고 변수에는 주소만이 할당된다. 여러 데이터 타입들이 저장될 수 있는 참조 자료형의 경우 일단 Heap 메모리에 크기를 만들고 Stack 메모리에 Heap 메모리의 주소(reference)를 할당하여 Heap 주소에 값들을 연결한다.

 

let arr = [1, "hi"];
let obj = {
    title: "홍길동전",
      price: 3000
};

이러한 형태로 저장되기 때문에 데이터는 자바스크립트 엔진이 Call Stack에서 주소값을 참조하여 Heap에 저장된 데이터를 가지고 올 수 있다.

 

let arr = [1, "hi"];
let obj = {
    title: "홍길동전",
      price: 3000
};
let obj2 = obj;

 

let str = "TypeScript!!";
let num = 1;
let num2 = num;

원시 자료형과 참조 자료형은 데이터를 복사할 때 그 특징을 알 수 있다. 위 코드처럼 참조 자료형은 obj2 변수에 obj를 복사하면 Heap에 새로운 데이터가 생기는 것이 아닌 기존 obj의 주소값을 복사해서 Call Stack에 할당한다. 원시 자료형은 num2 변수에 num을 복사하면 num2의 데이터가 Call Stack에 쌓인다. 즉, 원시 자료형은 값(value) 자체가 전달되고 참조 자료형은 주소(reference)가 전달된다.

 

바로 이러한 특징 때문에 완벽하게 일치하는 배열, 객체들의 비교 결과가 "거짓"이된다. 원시 자료형은 value 자체를 비교하기 때문에 1과 1은 같다고 판단되지만, 참조 자료형은 reference를 비교하는 것이기 때문에 따로 선언된 두 배열 혹은 객체의 비교는 언제나 false가 될 수밖에 없다.

댓글