티스토리 뷰

00. TL;DR

  • 자바스크립트의 값은 원시 타입과 객체 타입으로 나뉨
    • 원시 타입: number, string, boolean, undefined, null, symbol, bigint
    • 객체 타입: object (배열, 함수 포함)
  • 숫자 타입은 배정밀도 64비트 부동소수점(IEEE 754)을 따름
    • 0.1 + 0.2 !== 0.3: 부동소수점 오차 때문 (근사값 저장)
  • NaN은 자기 자신과도 같지 않은 유일한 값이며, Number.isNaN() 사용 권장
  • 배열은 내부적으로 객체 기반, CS에서 말하는 진짜 배열이 아님
  • 함수는 객체이며, 프로퍼티를 가질 수 있고 싱글턴 패턴에도 활용 가능
  • typeof는 타입 확인 연산자지만 null → object, 배열도 object이므로 주의
  • 템플릿 리터럴 앞에 함수를 붙이면 문자열-값 세트를 조립할 수 있음 (Tagged Template)

01. 자바스크립트의 데이터 타입

01.01. 데이터 타입 분류

자바스크립트의 모든 값은 데이터 타입을 갖으며, ES6는 7개의 데이터 타입을 제공하며 원시 타입과 객체 타입으로 분류됩니다.

구분 데이터 타입 설명
원시 타입 number 타입 숫자, 정수와 실수 구분없이 하나의 숫자 타입만 존재
원시 타입 string 타입 문자열
원시 타입 boolean 타입 논리적 참과 거짓
원시 타입 undefined 타입 var키워드로 선언된 변수에 암묵적으로 할당되는 값
원시 타입 null 타입 값이 없다는 것을 의도적으로 명시할 때 사용하는 값
원시 타입 symbol 타입 es6 에서 추가된 유일하고 변경 불가능한 데이터 타입, 주로 객체 속성의 키로 사용
원시 타입 bigint 타입 매우 큰 정수를 표현할 수 있는 타입, ES2020에서 추가
객체 타입 object 타입 객체, 함수, 배열 등

01.02. 원시 타입 (Primitive Types)

01.02.01. Number

자바스크립트는 모든 숫자에 대해서 하나의 타입만 존재합니다.

숫자 타입 값은 배정밀도(double precision) 64비트 부동소수점 형식을 따릅니다.

// 다음은 모두 숫자 타입

// 정수
var integer = 10;
// 실수
var double = 10.12;
// 음의 정수
var negative = -20;

// 65 - 2진수
var binary = 0b01000001;
// 65 - 8진수
var octal = 0o101;
//  65 - 16진수
var hex = 0x41;

위 코드에 작성된 것 외에도 숫자 타입은 3가지 특별한 값도 표현할 수 있습니다.

  • Infinity: 양의 무한대
  • -Infinity: 음의 무한대
  • NaN: 산술 연산 불가(not a number)
console.log(10 / 0); // Infinity
console.log(10 / -0); // -Infinity
console.log(10 / -0); // -Infinity
console.log(1 * "String"); // NaN

01.02.02. String

추가 자료:

 

문자열은 원시 자료형이지만 스택에 저장되지 않는다.

00. TL;DR자바스크립트에서 문자열은 불변(immutable)한 원시 타입이지만, 그 실제 데이터는 힙(Heap)에 저장되고, 스택에는 참조(reference) 만 남습니다. 01. 스택(Stack)과 힙(Heap)의 차이구분스택(Stack)힙(H

til-odin.tistory.com

 

자바스크립트 엔진의 문자열 관리 - 문자열 인터닝, 문자열 테이블

00. TL;DR문자열 인터닝은 문자열 값을 저장하고 재사용하기 위한 문자열 테이블(String Intern Table)을 이용합니다.문자열 테이블에 저장되는 것은 자바스크립트 코드에서 보이는 "객체"가 아니라, 엔

til-odin.tistory.com

 

문자열은 0개 이상의 16비트 유니코드 문자열 집합으로 전 세계 대부분의 문자를 표현할 수 있습니다.

문자열은 작은 따옴표(''), 큰 따옴표(""), 백틱(``)으로 텍스트를 감싸서 생성할 수 있습니다.

var string;
string = "문자열";
string = "문자열";
string = `문자열`;

템플릿 리터럴을 활용한 문자열 삽입:

var name = "Odin";
var greeting = `안녕하세요, ${name}님!`;
// 안녕하세요, Odin님!
console.log(greeting);

01.02.03. Boolean

불리언 타입의 값은 논리적 참, 거짓을 나타내는 true와 false 만 존재합니다.

var foo = true;
console.log(foo); // true

foo = false;
console.log(foo); // false

조건문에서의 활용:

var isAdult = 20 > 18;
if (isAdult) {
  console.log("성인입니다.");
}

01.02.04. Undefined

undefined는 값이 할당되지 않은 변수의 초기 값으로 사용됩니다.

var foo;
console.log(foo); // undefined;

자바스크립트 엔진이 변수를 초기화하는데 사용하는 undefined 값을 개발자가 의도적으로 변수에 할당한다면 undefined의 본래 취지와 어긋남으로 권장하지 않습니다. (null 사용 추천)

01.02.05. Null

null은 변수에 값이 없다는 것을 의도적으로 명시할 때 사용합니다.

var bar = null;
console.log(bar); // null

변수에 null을 재할당하는 것은 값이 비어있다고 알려주면 가비지 컬렉터가 메모리 회수하게 됩니다.

01.02.06. Symbol

심볼 값은 다른 값과 중복되지 않는 유일한 값입니다.

이름 충돌 위험이 없는 객체의 유일한 프로퍼티 키를 만들기 위해 사용합니다.

var key = Symbol("key");
console.log(key); // Symbol(key)

var obj = {};
obj[key] = "value";
console.log(obj[key]); // value

전역 심볼 레지스트리 사용:

var symbol1 = Symbol.for("mySymbol");
var symbol2 = Symbol.for("mySymbol");

console.log(symbol1 === symbol2); // true
console.log(Symbol.keyFor(symbol1)); // "mySymbol"

01.02.07. BigInt

BigInt는 안전한 정수 범위(Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER)를 초과하는 정수를 표현할 때 사용합니다.

const big = 1234567890123456789012345678901234567890n;
console.log(big);

// BigInt 연산은 같은 BigInt끼리만 가능
const a = 1n;
const b = 2n;
console.log(a + b); // 3n

BigInt와 Number 혼용 시 에러:

const c = 10n;
const d = 20;

console.log(c + d); // Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions

01.03. 객체 타입 (Object Types)

객체는 키-값 쌍의 집합입니다.

참조 타입으로, 변수는 객체의 메모리 주소를 참조하게 됩니다.

함수와 배열도 객체의 하위 타입으로 동적 속성 추가/삭제 가능합니다.

02. 심화 개념

02.01. Number 타입의 이슈: 배정밀도와 IEEE 754

02.01.01. 배정밀도란?

배정밀도(double-precision)는 컴퓨터에서 부동 소수점 수를 표현하는 방식 중 하나로, 64비트를 사용하여 수를 정밀하게 나타내는 방식을 말합니다.

자바스크립트를 포함한 많은 프로그래밍 언어에서 숫자를 표현할 때 이 배정밀도 방식을 사용합니다.

02.01.01.01. 배정밀도의 구성

배정밀도 64비트 부동 소수점 형식은 다음과 같이 구성됩니다.

  • 부호 비트 (1비트):
    • 양수 또는 음수를 나타냅니다.
  • 지수 비트 (11비트):
    • 소수점의 위치를 나타냅니다.
  • 가수 비트 (52비트):
    • 실제 숫자의 값을 나타냅니다.

02.01.01.02. 배정밀도의 중요성

배정밀도는 넓은 범위의 수를 정밀하게 표현할 수 있게 해줍니다.

하지만, 컴퓨터는 2진수를 사용하여 수를 표현하기 때문에 10진수 소수를 정확하게 2진수로 변환하지 못하는 경우가 발생합니다.

이로 인해 소수점 연산에서 미세한 오차가 발생할 수 있으며, 이는 '부동 소수점 오차' 또는 '배정밀도 오차'라고 불립니다.

02.01.01.03. 배정밀도와 관련된 이슈

  • 부동 소수점 오차:
    • 0.1 + 0.2와 같은 간단한 연산에서도 예상과 다른 결과가 나올 수 있습니다.
    • 이는 10진수 소수를 2진수로 변환하는 과정에서 발생하는 오차 때문입니다.
  • 정밀도 손실:
    • 매우 큰 수와 매우 작은 수를 함께 연산할 때 정밀도 손실이 발생할 수 있습니다.

자바스크립트는 IEEE 754 표준에 따라 배정밀도 64비트 부동 소수점 형식을 사용합니다.

02.01.02. IEEE 754는 무엇인가?

IEEE 754는 컴퓨터에서 실수를 정확하고 효율적으로 표현하고 연산하기 위한 표준형식 입니다.

이 형식을 따르는 언어들은 c/c++(float, double), java(float, double), python(float), c#(float, double)들이 있습니다.

02.01.02.01. 6.375를 IEEE 754 배정밀도 변환 순서

  1. 십진수 → 이진수로 변환
정수부: 6 → 110
소수부: 0.375 → 0.011  (0.375 × 2 = 0.75 → 0 / 0.75 × 2 = 1.5 → 1 / 0.5 × 2 = 1.0 → 1)

⇒ 6.375 = 110.011 (2진수)
  1. 정규화 (Normalized Form)
110.011 → 1.10011 × 2^2
  1. 부호 비트
6.375는 양수 → 0
  1. 지수 계산
- 실제 지수: 2
- Bias: 1023 (2 ** 11(배정밀도는 11 자리의 지수를 갖음) / 2 - 1)
- 저장할 지수: 2 + 1023 = 1025

⇒ 1025 → 10000000001 (11비트)
  1. 가수 계산
- 정규화된 1.10011에서 앞의 1.은 생략하고, 뒤의 10011을 52비트로 채움:

1001100000000000000000000000000000000000000000000000 (52비트)

02.01.03. 0.1 + 0.2 !== 0.3인 이유

02.01.03.01. 원인

  • 10진수 소수 0.1과 0.2는 2진수로 변환하면 무한 소수가 됩니다.
  • 컴퓨터는 유한한 메모리 공간에 이 무한 소수를 저장해야 하므로, 특정 지점에서 반올림하여 근사값으로 저장합니다.
  • 이러한 반올림 과정에서 발생하는 작은 오차를 부동소수점 오차라고 합니다.
  • 0.1과 0.2를 더할 때, 각각의 근사값을 더하므로 결과는 0.3에 매우 가까운 값이지만 정확히 0.3은 아닙니다.

02.01.03.02. 0.1이 메모리에 저장될때 어떻게 저장될가

  1. 10진수를 2진수로 변환합니다.
    • 0.1 = 0.00011001100110011... (2진수)
  2. 부동 소수점 형식으로 표현합니다.
    • IEEE 754 표준에서는 부동소수점을 부호(sign), 지수(exponent), 가수(mantissa)로 나누어 표현합니다.

02.01.03.03. 10진수가 2진수로 변환되는 과정

10진수 0.1을 2진수로 변환하는 과정은 다음과 같습니다.

1. 정수 부분 변환:

  • 0.1의 정수 부분은 0이므로, 2진수 정수 부분도 0입니다.

2. 소수 부분 변환:

  • 소수 부분 0.1에 2를 곱합니다.
    • 0.1 * 2 = 0.2 (정수 부분: 0)
  • 결과의 소수 부분에 다시 2를 곱합니다.
    • 0.2 * 2 = 0.4 (정수 부분: 0)
    • 0.4 * 2 = 0.8 (정수 부분: 0)
    • 0.8 * 2 = 1.6 (정수 부분: 1)
    • 0.6 * 2 = 1.2 (정수 부분: 1)
    • 0.2 * 2 = 0.4 (정수 부분: 0)
    • 0.4 * 2 = 0.8 (정수 부분: 0)
    • 0.8 * 2 = 1.6 (정수 부분: 1)
    • 0.6 * 2 = 1.2 (정수 부분: 1)
  • 이 과정을 계속 반복하면 0과 1이 반복되는 패턴이 나타납니다.
  • 그러므로 0.1의 2진수 소수 부분은 0.0001100110011... 이 됩니다.

3. 결과 조합:

정수 부분과 소수 부분을 조합하면 0.1의 2진수 표현은 0.00011001100110011... 이 됩니다.

0.1이 실제 저장된 모습:

0.1 in IEEE 754 (64-bit float):
Sign: 0
Exponent: 01111111011
Mantissa: 1001100110011001100110011001100110011001100110011001 (반복)

02.01.03.04. 무한 반복되지 않는 소수

컴퓨터에서 2진수로 정확하게 표현될 수 있는 10진수 소수점은 분모가 2의 거듭제곱인 분수로 표현될 수 있는 소수점입니다.

1/2, 1/4, 1/8, 1/16

0.5 (1/2)
0.25 (1/4)
0.125 (1/8)
0.0625 (1/16)

02.01.03.05. 해결 방법들

Number.EPSILON

부동소수점 간의 비교에서 === 대신 허용 오차(EPSILON)를 두고 비교합니다.

function isEqual(a, b) {
  return Math.abs(a - b) < Number.EPSILON;
}

console.log(0.1 + 0.2 === 0.3); // false
console.log(isEqual(0.1 + 0.2, 0.3)); // true
정수 변환후 나누기
// 예: 0.1 + 0.2 → 1 + 2 = 3 → 다시 나누기
function preciseAdd(a, b) {
  const scale = 10; // 0.1 단위일 경우
  return (a * scale + b * scale) / scale;
}

console.log(preciseAdd(0.1, 0.2)); // 0.3
toFixed() 사용

반올림 처리되며, 항상 소수점 이하 자릿수를 기준으로 문자열 생성

// toFixed 사용 예시
console.log((0.1 + 0.2).toFixed(2)); // '0.30'
toPrecision() 사용

반올림 처리되며, 전체 유효 숫자 자릿수 고정

console.log((1.5 + 1.012).toPrecision(2)); // '2.5'
외부 라이브러리 사용 (추천)
import Big from "big.js";

const a = new Big(0.1);
const b = new Big(0.2);
const c = a.plus(b);

console.log(c.toString()); // '0.3'

02.02. NaN

02.02.01. NaN 값이란

NaN은 Not a Number 의 줄임말로, 숫자 연산을 시도했지만 결과가 유효한 숫자가 아닌 경우를 나타냅니다.
자바스크립트에서는 NaN 자체가 숫자 타입(Number) 에 속합니다.

console.log(typeof NaN); // "number"

NaN은 다음과 같은 경우에 발생합니다:

console.log('문자열' - 1);      // NaN
console.log(0 / 0);             // NaN
console.log(Math.sqrt(-1));     // NaN
console.log(parseInt('abc'));   // NaN

02.02.02. NaN 판단 방법

NaN은 자바스크립트에서 자기 자신과도 같지 않은 유일한 값입니다.

const x = NaN;

console.log(x === NaN); // false ❌
console.log(x !== x);   // true ✅

이 특징을 이용하여 다음과 같이 NaN 여부를 확인할 수 있습니다:

서로 다른 같지 않음으로 비교:

function isReallyNaN(value) {
  return value !== value;
}

Number.isNaN으로 비교:

Number.isNaN(NaN); // true

Object.is로 비교:

Object.is(NaN, 1 * 'a'); // true

ES6 이후에는 Object.is() 또는 Number.isNaN()을 사용하는 것이 더 안전합니다.

02.02.03. isNaN vs Number.isNaN

함수 동작 방식 주의점
isNaN(value) 암묵적 타입 변환 후 NaN 여부를 판단 숫자가 아닌 값도 NaN으로 간주할 수 있음
Number.isNaN(value) 엄격하게 NaN인 경우만 true 반환 숫자형 NaN 판별 전용
// isNaN: 문자열도 내부적으로 숫자로 변환 후 NaN이면 true
console.log(isNaN('abc'));          // true ❗️
console.log(isNaN(undefined));      // true ❗️

// Number.isNaN: NaN일 때만 true
console.log(Number.isNaN('abc'));   // false ✅
console.log(Number.isNaN(NaN));     // true ✅

실무에서는 Number.isNaN()을 사용하는 것이 더 정확하고 안전합니다.

02.03. 지수 표기법

매우 크거나 작은 숫자를 간단히 표현하는 방법입니다.

a × 10^n 형태를 ae+n 또는 ae−n 처럼 표현하는것을 말합니다.
(e는 exponent 이므로 지수 표기 단위에 e가 사용됩니다.)

1.23e3 → 1.23 × 10³ → 1230    // e3: 소수점이 오른쪽으로 3칸 이동

5.6e-4 → 5.6 × 10⁻⁴ → 0.00056 // e-4: 소수점이 왼쪽으로 4칸 이동

02.03.01. 지수 표현식이 표현되는 경우

일반적으로 아주 크거나 아주 작은 수를 출력할 때 자동으로 표현됩니다.

자동으로 표현되는 경우:

console.log(2200000000000000000000);   // 2.2e+21
console.log(-2200000000000000000000);  // -2.2e+21

개발자가 명시적으로 표현하는 경우:

console.log((123).toExponential());   // '1.23e+2'

// ❗️ 자리수를 지정하면 반올림 처리 됨
console.log(+(100500).toExponential(2)); // 101000

02.04. 템플릿 리터럴 함수 (Tagged Template Literal)

템플릿 리터럴 앞에 함수를 붙이면, 문자열(strings)과 값(values)이 쌍을 이루는 세트로 전달되어,
함수가 조립하거나 가공할 수 있게 하는 문법입니다.

02.04.01. 규칙

const tag = (strings, ...values) => {
  console.log(strings); //  ['Hello ', ', you have ', ' messages.']
  console.log(values); //  ['Odin', 777]
  return 'aaa'
}
tag`Hello ${'Odin'}, you have ${777} messages.`

위와 같이 문자열과 값은 항상 세트로 묶여(값이 문자열보다 -1만큼 작음) 전달됩니다.

문자열[0] + 값[0] + 문자열[1] + 값[1] + ... + 문자열[n]

이런 세트 규칙을 이용하여 다음과 같이 코드를 작성할 수 있습니다.

function joinTagged(strings, ...values) {
  let result = '';

  for (let i = 0; i < values.length; i++) {
    result += strings[i] + values[i];  // 세트 조립: 문자열 + 값
  }

  result += strings[values.length];    // 마지막 남은 문자열 추가

  return result;
}

02.04.02. 응용 - 문자에 포함된 숫자 포멧팅

const format = (strings, ...values) => {
  const format = (v) =>
    typeof v === 'number' ? '₩' + v.toLocaleString('ko-KR') : v;

  let result = '';

  for (let i = 0; i < values.length; i++) {
    result += strings[i] + format(values[i]);
  }

  result += strings[values.length];
  return result;
}

const name = 'Odin';
const price = 1234567;

const message = format`${name}님, 결제 금액은 ${price}입니다.`;
console.log(message);
// Odin, 결제 금액은 ₩1,234,567입니다.

02.04.03. 응용 - 다국어 포멧팅

const messages = {
  ko: {
    'Hello {0}, you have {1} messages.': '안녕 {0}님, 메시지 {1}개 있어요.'
  },
  en: {
    'Hello {0}, you have {1} messages.': 'Hello {0}, you have {1} messages.'
  }
};

let currentLang = 'ko';

const i18n = (strings, ...values) => {
  // 1. 원본 키 만들기 (values 자리는 {0}, {1}, ...)
  let key = '';

  for (let i = 0; i < strings.length; i++) {
    key += strings[i];
    if (i < values.length) {
      key += `{${i}}`;
    }
  }

  // 2. 현재 언어로 번역된 템플릿 찾기
  const translated = messages[currentLang][key] ?? key;

  // 3. 값 치환
  return translated.replace(/\{(\d+)\}/g, (_, index) => values[index]);
}

const name = 'Odin';
const count = 3;

const msg = i18n`Hello ${name}, you have ${count} messages.`;
console.log(msg);
// 출력: 안녕 Odin, 메시지 3개 있어요.

02.04.04. 응용 - styled component

const styledTag = (strings, ...values) => {
  return (props) => {
    const style = {};
    let fullStyleText = '';

    for (let i = 0; i < values.length; i++) {
      const str = strings[i];
      const val = typeof values[i] === 'function' ? values[i](props) : values[i];
      fullStyleText += str + val;
    }

    fullStyleText += strings[values.length]; // 마지막 문자열 붙이기

    // style 문자열을 객체로 파싱
    fullStyleText
      .split(';')
      .map(rule => rule.trim())
      .filter(Boolean)
      .forEach(rule => {
        const [key, val] = rule.split(':').map(part => part.trim());
        const camelKey = key.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
        style[camelKey] = val;
      });

    const div = document.createElement('div');
    Object.assign(div.style, style);
    div.textContent = props.children ?? '';

    return div;
  };
};


const styledDiv = styledTag`
  background: ${props => props.bgColor};
  color: ${props => props.textColor};
  padding: 12px;
  font-weight: bold;
`;

const el = styledDiv({
  bgColor: 'tomato',
  textColor: 'white',
  children: '바닐라 JS도 된다!'
});

console.log(el);

02.06. typeof 연산자

typeof 연산자는 피연산자의 데이터 타입을 문자열로 반환하는 연산자입니다.
변수가 저장하고 있는 값의 데이터 타입을 확인할 때 주로 사용됩니다.

02.06.01. typeof 연산자의 반환값

typeof 연산자의 반환값은 총 7가지입니다.

타입 typeof 결과값 설명
숫자(Number) 'number' 정수, 소수, Infinity, NaN 모두 포함
문자열(String) 'string' 모든 문자열
불리언(Boolean) 'boolean' true 또는 false
정의되지 않음 'undefined' 값이 아직 할당되지 않은 변수
심볼(Symbol) 'symbol' ES6부터 추가된 고유하고 변경 불가능한 값
객체(Object) 'object' 배열, 객체, null 모두 포함
함수(Function) 'function' 함수(모든 종류의 함수 표현식 포함)

02.06.02. 주의 사항

  • null의 타입이 object로 나오는 것은 자바스크립트 설계상의 오래된 오류입니다.
  • 배열은 typeof 연산자에서 'object'로 나옵니다.

null 검증:

let data = null;

if (typeof data === "object" && data !== null) {
  // 객체 처리
} else if (data === null) {
  console.log("데이터가 null입니다.");
}

배열 검증:
배열은 Array 메서드인 Array.isArray()로 판별해야 합니다.

Array.isArray([]); // true

02.06.03. 선언되지 않은 변수의 가드 처리

자바스크립트에서는 선언되지 않은 변수를 읽으려고 하면 ReferenceError가 발생하여 코드가 중단됩니다.

선언되지 않은 변수를 체크할 때는 typeof 연산자를 이용할 수 있습니다.

// 브라우저 환경에서의 window 객체 체크
if (typeof window !== 'undefined') {
  console.log('브라우저 환경입니다.');
}

// Node.js 환경에서의 process 객체 체크
if (typeof process !== 'undefined') {
  console.log('Node.js 환경입니다.');
}

02.07. 배열은 CS 에서 말하는 배열과 다르게 구현되어 있다.

02.07.01. CS 에서 이야기하는 배열

컴퓨터 공학(Computer Science, CS)에서 일반적으로 말하는 배열(Array)은 다음과 같은 특징을 가집니다.

  1. 메모리에 연속적(Contiguous) 으로 저장됩니다.
  2. 고정된 크기를 가집니다. (생성 시 크기 고정)
    • CS에서의 배열은 크기가 고정되어 있어 배열의 크기를 변경하려면 아래와 같은 과정을 거쳐야 합니다.
    • 새로운 배열을 더 큰 크기로 생성하고,
    • 기존 배열의 모든 요소를 새로운 배열로 복사한 다음,
    • 기존 배열을 삭제(메모리 해제) 합니다.
  3. 배열 내의 각 원소는 동일한 크기와 타입을 가집니다.
  4. 원소에 접근하는 데 시간 복잡도가 O(1) 입니다.

02.07.02. 자바스크립트의 배열

자바스크립트의 배열은 실제로는 해시 테이블(Hash Table)을 활용한 객체(Object)로 구현되어 있지만 희소 배열과 같은 인터페이스를 제공합니다.

  1. 메모리 연속성을 보장하지 않습니다.
  2. 배열의 크기가 동적(Dynamic)으로 변합니다. (자동으로 늘어남)
  3. 배열의 각 원소는 다른 타입의 데이터를 가질 수 있습니다.
  4. 원소 접근은 객체의 키(인덱스)를 통해 이루어집니다.
  5. 내부적으로는 배열 인덱스를 문자열 키로 변환하여 저장합니다.
const arr = [1, '문자', { id: 123 }, [1, 2, 3]];
arr.push(true); // 동적으로 추가 가능
console.log(arr[1]); // '문자'

위 코드를 확인하면 다음과 같은구조를 갖습니다.

{
  '0': 1,
  '1': '문자',
  '2': { id: 123 },
  '3': [1, 2, 3],
  length: 4
}

02.07.03. 자바스크립트에서 배열이 배열이 아닌 이유는 뭘까

  1. 유연성과 편리성: 배열 크기나 타입 변경이 자유롭고 쉬워야 했음.
  2. 객체 기반 언어 특성: 모든 것이 객체로 다루어지는 철학과의 일관성 유지
  3. 사용자 중심 접근: 사용자의 생산성과 직관성을 우선 고려하여 설계

02.07.04. 희소 배열

희소 배열이란 배열에서 연속된 인덱스 중간에 빈(empty) 요소들이 많은 배열을 의미합니다.
즉, 배열 인덱스가 순차적으로 채워지지 않고 중간이 비어있는 배열을 말합니다.

희소 배열 특징:

  1. 중간의 비어있는 요소는 메모리를 차지하지 않습니다. (빈 요소는 실제 메모리에 값이 할당되지 않음)
  2. 메서드에 따라 빈 요소는 처리되지 않을 수 있습니다.
const arr = [1];
arr[100000000000] = 100;

for (const key in arr) {
  console.log(key, arr[key]);
}

아래 코드는 왜 동작을 안할가?

const arr = [1];
arr[100000000000] = 100;

arr.forEach((item, index) => {
    console.log(item, index)
});

자바스크립트 배열의 인덱스는 내부적으로 32비트 부호 없는 정수(unsigned 32-bit integer) 형태로 처리됩니다.

배열의 최대 유효 인덱스는 2^32 - 2 (4,294,967,294) 이므로

이 값을 초과하는 인덱스는 일반적인 배열 요소가 아닌 프로퍼티로 취급되기 때문에 100000000000 인덱스는에 대한 함수는 호출되지 않습니다.

02.08. 함수도 객체의 특성을 갖는다.

자바스크립트에서 함수(Function)는 특별한 유형의 객체(Object)입니다.

즉, 자바스크립트에서는 함수 또한 프로퍼티와 메서드를 가질 수 있는 객체로 취급됩니다.

02.08.01. 객체 증명

function greet() {
    console.log('안녕하세요!');
}

// 객체처럼 프로퍼티 추가 가능
greet.message = '반갑습니다!';
console.log(greet.message); // '반갑습니다!'
function Singleton(name, age) {
    if(Singleton._instance) {
        return Singleton._instance;
    }
    this.getName = function() { 
        return name;
    }
    this.getAge = function() {
        return age;
    }

    Singleton._instance = this;
}

var a = new Singleton('odin', 10);
var b = new Singleton('james', 20);

console.log(a === b); // true
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
글 보관함