[JS] 자바스크립트 데이터 타입(Data Type)

IMJOne·2023년 2월 28일

JavaScript

목록 보기
2/5
post-thumbnail

변수를 선언하고 값을 할당하면 메모리 어딘가에 값이 저장되고, 변수는 해당 메모리의 주소를 가리키게 된다. 자바스크립트는 느슨한 타입(loosely typed)의 동적(dynamic) 언어로, 변수가 특정 타입과 연결되지 않으며 모든 타입의 값으로 할당 및 재할당이 가능하다. (weekly typed) 이번 포스팅에서는 자바스크립트의 기본적인 데이터 타입의 종류에 대해 정리해보고자 한다.


🤔 데이터 타입 (Data Type)

데이터 타입이란 프로그래밍 언어에서 사용할 수 있는 데이터의 종류를 말한다.
자료형이라고도 불리며, 자바스크립트에서는 크게 두 가지 카테고리로 나누어볼 수 있다.

  • 단일 데이터를 담을 수 있는 원시 타입(Primitive Type)
  • 복합 데이터를 담을 수 있는 객체 타입(Object Type)

📌 원시 타입 (Primitive Type)

원시 타입은 단 하나의 데이터만을 담을 수 있으며, 총 7개의 타입이 존재한다.

  • 단일 데이터
  • number, bigint, string, boolean, null, undefined, symbol
  • 값에 의한 복사 (Copy by Value)

💡 원시 타입은 크기가 정해져 있으며, 스택(Stack) 이라는 메모리 영역에 보관된다.


1. 숫자 (Number)

자바스크립트는 정수와 실수 구분 없이 단 하나의 숫자 타입만 존재한다.

const integer = 123;   // 정수
const negative = -123; // 음수
const decimal = 1.23;  // 소수
const zero = 0 / 123;  // 0

const infinity = 123 / 0; // Infinity 
const negativeInfinity = -123 / 0; // -Infinity
const nAn = "not a number" / 123;  // NaN

2. 문자열 (String)

문자열의 길이에는 상관 없이 string이라는 데이터 타입으로 값이 생성된다.
ES6부터 도입된 템플릿 리터럴(${})을 사용하면 줄바꿈 및 공백, 변수 등 모두 적용된다.

// String
const char = "togetger";
const weather = "sunny";
console.log("happy", char);
console.log("Its " + weather + " today");

// Template literals
const world = "World";
const greeting = "Hello " + world;
console.log(`${greeting}, welcome!😊`); // Hello World

3. 불리언 (Boolean)

boolean 타입의 값은 논리적 참 / 거짓을 나타내는 truefalse 뿐이다.

  • Falshy - 0, -0, null, undefined, NaN, '' (빈 문자열)
  • Truthy - 1, -1, '0', 'text', {}, [], Infinity, -Infinity 등 다른 모든 값들
// Boolean
const truth = true;
const lie = false;
const large = 3 > 1; // true
const small = 3 < 1; // false

// Truthy 참인 값
console.log(!!1);
console.log(!!-1);
console.log(!!'0');
console.log(!!'text');
console.log(!!{});
console.log(!![]);
console.log(!!Infinity);
console.log(!!-Infinity);

// Falshy 거짓인 값
console.log(!!0);
console.log(!!-0);
console.log(!!null);
console.log(!!undefined);
console.log(!!NaN);
console.log(!!'');

4. null

변수를 선언하고 빈 값을 할당한 상태로,
해당 변수가 어떠한 객체도 가리키고 있지 않으며 명시적으로 비어 있음을 나타낸다.

let none = null;
console.log(none); // null

5. undefined

변수를 선언하고 아무런 값도 할당하지 않은 상태로,
해당 변수에 값이 있는지 없는지 조차 정해지지 않았음을 나타낸다.

let undefn = undefined;
let noting;
console.log(undefn); // undefined
console.log(noting); // undefined

💡nullundefined의 차이점

기본적으로 둘 다 값이 없음을 나타내지만, 차이점은 분명히 존재한다.

  • null - 확실하게 비어 있는 상태, 메모리 상에 null 이라는 오브젝트가 들어가 있음
  • undefined - 정해지지 않은 상태, 메모리 상에 아무런 것도 들어 있지 않음

    실제로 typeof 연산자를 통해 자료형을 확인해보면
    nullobject, undefinedundefined가 출력되는 것을 확인해볼 수 있다.

6. 심볼 (Symbol)

ES6에서 새롭게 추가된 데이터 타입으로, 유일한 키를 생성할 수 있다.
인자로 전달된 문자열(키의 이름)을 가리키는 고유한 식별자를 반환한다.
동일한 이름으로 여러 개의 심볼을 생성해도 각각 다른 키를 가지게 된다.

const symbol1 = Symbol('key');
const symbol2 = Symbol('key');
console.log(typeof symbol1); // symbol
console.log(symbol1 === symbol2); // false

만약 동일한 이름으로 하나의 키를 사용하고 싶다면 Symbol.for()을 이용할 수 있다.
Symbol.for()을 통해 생성한 심볼은 전역 심볼 레지스트리(Global Symbol Registry)에 저장되며, 해당 이름에 대한 문자열을 요구할 때마다 동일한 심볼을 재사용한다.

const gSymbol1 = Symbol.for('key');
const gSymbol2 = Symbol.for('key'); // string이 같다면 동일한 symbol로 인식
console.log(gSymbol1 === gSymbol2); // true

심볼의 문자열을 알고 싶다면 keyFor() 메소드를 사용할 수 있다.
단, keyFor()은 전역 심볼 레지스트리에 보관된 심볼에 한해서만 이름을 가져올 수 있다.
일반 심볼은 문자열에 대한 정보가 숨겨져 있기 때문에 외부에서 조회할 수 없으며, description을 통해 문자열로 변환한 후 접근해야 한다.

const key1 = Symbol('key');
const key2 = Symbol.for('key');
console.log(Symbol.keyFor(key1)); // undefined
console.log(key1.description);    // key
console.log(Symbol.keyFor(key2)); // key

📌 객체 타입 (Object Type)

객체 타입은 여러 가지 데이터를 함께 묶어서 담을 수 있다.

자바스크립트에서 원시 타입을 제외한 모든 값은 객체(Object)로 취급한다. 객체란 연관된 데이터를 함께 묶어놓은 것으로, { key: value } 형태로 이루어진 프로퍼티의 집합체이다. 배열(Array)함수(Function) 또한 객체로 표현되며, 객체의 프로퍼티로 지정할 수도 있다. 객체의 프로퍼티가 함수인 경우 이를 메소드(Method)라고 부른다.

  • 복합 데이터
  • 원시 타입을 제외한 나머지 모든 것들 (object, array, function…)
  • 참조에 의한 전달 (Copy by Reference)

💡 객체 타입은 크기가 정해져 있지 않으며, 힙(Heap) 이라는 메모리 영역에 보관된다.

const person = {
  name: 'jone',
  age: 24,
  getInfo: function() {
    return `${this.name}, ${this.age}`;
  },
};

console.log(person.name, person.age); // jone 24
console.log(person.getInfo()); // jone, 24

✨ 값과 참조의 차이

원시 타입과 객체 타입은 값을 복사할 때에도 큰 차이가 있다. 원시 타입은 값 자체가 복사되어 전달되며, 이것을 값에 의한 복사(Copy by Value)라고 한다. 반면에 참조 타입은 실제 값이 아닌 참조값이 복사되어 전달되며, 이것을 참조에 의한 복사(Copy by Reference)라고 한다.


✔️ 값에 의한 복사

  • 값이 복사되어 전달
  • 원본과 복사본이 서로 영향을 주지 않음

변수에 원시 타입을 할당하면 값(value) 자체가 메모리 셀 안에 바로 저장되며,
해당 변수는 값이 저장되어 있는 메모리를 직접적으로 가리키게 된다.

따라서 다른 변수에 할당하거나 함수의 매개변수로 전달하는 경우, 원본 값이 그대로 복사되어 전달된다. 서로 독립적인 값을 가지고 있기 때문에 원본 데이터의 값이 바뀌더라도 복사한 데이터의 값은 변경되지 않는다. 이를 깊은 복사(Deep Copy) 라고 한다.

let a = 1;
b = a;

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

b = 2;

console.log(a === b); // false
console.log(a); // 1
console.log(b); // 2

위의 예시처럼 원시 타입을 다른 변수에 할당하는 경우, 값에 의한 복사가 이루어지므로 두 변수는 동일한 값을 가지게 된다. 이 때 b에 다시 2를 재할당하면, b가 가리키고 있는 메모리 안에 2 라는 값이 새롭게 저장된다. 즉, b의 값만 변경되었기 때문에 a는 여전히 1을 가지고 있는 것을 볼 수 있다.


✔️ 참조에 의한 복사

  • 참조값이 복사되어 전달
  • 원본과 복사본이 서로 영향을 미침

객체 타입은 참조 타입(Reference Type)이라고도 불린다.
변수에 객체 타입을 할당하면 객체 자체가 저장되는 것이 아닌 실제로 객체가 들어 있는 메모리의 주소 즉, 참조값(reference)이 메모리 셀 안에 저장되며, 해당 변수는 이 참조값이 저장된 메모리를 가리키게 된다.

따라서 다른 변수에 할당하거나 함수의 매개변수로 전달하는 경우, 원본 객체의 참조값이 복사되어 전달된다. 동일한 주소에 있는 객체를 서로 공유하기 때문에 원본 데이터의 값이 바뀌면 복사한 데이터의 값도 변경된다. 이를 얕은 복사(Shallow Copy) 라고 한다.

let apple = { name: 'apple', emoji: '🍎' };
let orange = apple;

console.log(apple === orange); // true

apple.name = 'orange';
console.log(orange.name); // orange

위의 예시처럼 객체 타입을 다른 변수에 할당하는 경우, 참조에 의한 복사가 이루어지므로 두 변수는 동일한 메모리 주소를 가지게 된다. 즉, 각 변수에 담겨 있는 메모리 주소가 가리키는 객체의 원본이 동일하다는 말이다. 따라서 apple의 프로퍼티를 변경하면 orange의 프로퍼티 또한 업데이트되기 때문에 이 점을 꼭! 주의해야 한다.

profile
Front-end developer with enjoys coding

0개의 댓글