{ }codelper

배우기 › JavaScript

언어마다 다른 것 · 41

자바스크립트의 같음과 참·거짓

== 과 ===, 거짓 같은 값, ?? 와 ||, 실수 하나뿐인 수, undefined 와 null, 그리고 TypeScript가 막아 주는 것.

이 단원은 JavaScript · TypeScript에서 배워요.
다른 언어는 비교할 때 타입을 몰래 바꾸지 않아요.
Python "5" == 5는 그냥 False(크기 비교 "5" < 5는 TypeError), Java·C#은 컴파일 오류라 직접 변환해야 하고, 크레이콘 ==도 타입이 다르면 거짓이에요.

JavaScript는 비교하거나 참·거짓을 볼 때 타입을 몰래 바꿔요.
아래 예제는 입력으로 읽은 문자열 "5"와 "0"으로 ==와 ===, ||와 ??, 실수 계산, undefined와 null이 어떻게 다르게 나오는지 보여 줘요.

const [a, b] = require("fs").readFileSync(0, "utf8").trim().split("\n"); console.log(a == 5, a === 5, a === "5");console.log(a + 1, Number(a) + 1);console.log(0 == "", null == undefined, null === undefined); const falsy = [0, "", NaN, null, undefined, false];console.log(falsy.filter(Boolean).length, Boolean("0"), Boolean([])); const count = Number(b);console.log(count || 10, count ?? 10); console.log(0.1 + 0.2, 0.1 + 0.2 === 0.3);console.log(Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON);console.log(Number.MAX_SAFE_INTEGER + 2);console.log(String(2n ** 64n)); const nan = Number("abc");console.log(nan === nan, Number.isNaN(nan)); const user = { name: "Kim" };console.log(user.age, typeof null, user.age ?? "none");
stdin
5
0
stdout
true false true
51 6
true true false
0 true true
10 0
0.30000000000000004 false
true
9007199254740992
18446744073709551616
false true
undefined object none

핵심

  • ==는 타입이 다르면 한쪽을 바꿔서 비교해요.
    그래서 "5" == 5, 0 == "", null == undefined가 모두 true예요.
  • ===는 타입까지 같아야 해요.
    바꾸는 규칙이 복잡하니 외우기보다 늘 ===와 !==를 써요.
  • +는 한쪽이 문자열이면 이어 붙여요.
    "5" + 1은 "51"인데 "5" - 1은 4예요.
    입력은 늘 문자열이니 먼저 Number(...)로 바꿔요.
  • 거짓 같은 값(falsy)은 false, 0, -0, 0n, "", null, undefined, NaN뿐이에요.
    "0"과 빈 목록 []은 참이에요(Python은 []가 거짓).
  • '값이 없음'이 둘이에요.
    undefined는 넣은 적이 없다는 뜻(없는 속성, 안 준 매개변수, return 없는 함수의 값)이고, null은 일부러 넣은 "비어 있음"이에요.
    둘 다 물을 때는 x == null이나 x ?? 기본값을 써요.
  • NaN은 자기 자신과도 같지 않아서 NaN === NaN이 false예요.
    Number.isNaN(x)로 물어요.
    typeof null이 "object"인 건 초기 JavaScript의 실수가 남은 거예요.

언어별로 쓰는 법

JavaScript비교는 ===·!==, 기본값은 ??, 문자열은 Number(...)로 수로 바꿔요.
이 함정들은 실행 중에 아무 경고 없이 지나가요
TypeScript일부를 컴파일할 때 막아요: a == 5(string과 number)는 TS2367, x === NaN은 TS2845, 타입에 없는 user.age는 TS2339.
strict에서는 age?: number를 쓰기 전에 undefined인지 확인하게 해요.
하지만 타입은 실행 전에 지워져서 실행 중에는 그대로 JavaScript이고, any나 as를 쓰면 검사가 꺼져요(예제의 raw)

자주 하는 실수

기본값을 ||로 줬어요

const count = 0;
console.log(count || 10, count ?? 10);

→ 10 0 — ||는 왼쪽이 거짓 같으면 오른쪽을 줘서 올바른 값 0이 10으로 바뀌어요

null·undefined일 때만 오른쪽을 주는 ??를 써요.

실수를 ===로 비교했어요

console.log(0.1 + 0.2);
console.log(0.1 + 0.2 === 0.3);

→ 0.30000000000000004, false — 수는 모두 64비트 실수(double) 하나라서 오차가 생겨요

Math.abs(x - y) < Number.EPSILON처럼 차이로 비교해요.

아주 큰 정수를 그냥 계산했어요

console.log(Number.MAX_SAFE_INTEGER + 2);

→ 9007199254740992 — 정수는 2^53 − 1(9007199254740991)까지만 정확해서 ...993이 나오지 않아요

2n 64n처럼 n을 붙인 BigInt**로 계산해요.
1n + 1처럼 보통 수와 섞으면 TypeError예요.

언어마다 다른 점
비교는 ===, 기본값은 ??로 쓰세요.
==와 ||는 "5" == 5가 참이 되거나 0이 10으로 바뀌는 것처럼 오류 없이 다른 답을 내요.

연습 문제