다음 책들과 MDN의 내용을 모아 자바스크립트 핵심 위주로 정리해 보았습니다. 여러 권의 책을 한 글로 훑어볼 수 있도록 최대한 간결하게 정리하겠습니다.
모던 자바스크립트 Deep Dive - 이웅모
You Don’t Know JS - Kyle Simson
자바스크립트는 왜 그 모양일까?(How JavaScript Works) - Douglas Crockford
자바스크립트 완벽 가이드(JavaScript: The Definitive Guide 7/E) - David Flanagan
자바스크립트에는 18437736874454810627개의 불변 숫자 객체가 내장되어 있는데, 각각은 고유하게 숫자를 나타냅니다. 숫자 리터럴은 각 리터럴의 값과 가장 잘 맞는 숫자 객체에 대한 참조를 생성합니다. 어떤 경우에는 딱 맞는 값이고, 어떤 경우에는 실제 값과 9.979201547… 만큼 차이가 나기도 합니다.
더글러스 크락포드 , 『자바스크립트는 왜 그 모양일까?』, 인사이트(2020), p15.
The JavaScript
Number
type is a double-precision 64-bit binary format IEEE 754 value, likedouble
in Java or C#.
자바스크립트Number
타입은 Java 또는 C#의 double과 같은 배정밀도 64비트 부동소수점 형식 IEEE 754 을 따릅니다.
mdn - JavaScript data types and data structures
자바스크립트는 숫자형이 하나뿐이라는 이유로 자주 비판받았지만, 사실 이는 자바스크립트의 아주 큰 강점 중 하나입니다. 비슷한 여러 가지 타입 중에서 혹시 잘못된 타입을 사용할까 봐 고민하며 시간을 낭비하지 않아도 되니 개발자의 생산성이 증가합니다. 타입 변환으로 인한 오류도 없습니다. int형을 사용해서 발생하는 오버플로 문제도 발생하지 않습니다. 오버플로가 발생하지 않기 때문에 자바스크립트의 정수는 자바의 정수보다 훨씬 안정적입니다.
더글러스 크락포드 , 『자바스크립트는 왜 그 모양일까?』, 인사이트(2020), p13-14.
0
3
100000
0xff // 255 (15*16 + 15)
0xBADCAFE // 195939070
0b1010 // 21 (1*16 + 0*8 + 1*4 + 0*2 + 1*1)
0o377 // 255 (3*64 + 7*8 + 7*1)
3.14
2345.6789
6.02e23 // 6.02 x 10^23
let billion = 1_000_000_000; // 1000 단위 구분자로 사용
let bytes = 0x89_AB_CD_EF; // 바이트 구분자로 사용
자바스크립트 숫자는 대단히 정밀한 편이며 0.1을 아주 가깝게 표현합니다. 하지만 가까울 뿐 완전히 정확한 것은 아니기 때문에 문제가 생길 수 있습니다. 다음 예제를 보십시오.
let x = .3 - .2; let y = .2 - .1; x === y // false x === .1 // false y === .1 // true
...부동 소수점 근삿값 때문에 프로그램에 문제가 생긴다면 정수로 변환하는 것을 고려해 보십시오.
데이비드 플래너건 , 『자바스크립트 완벽 가이드』, 인사이트(2022), p33.
2진 부동소수점 시스템을 처음 사용한 사람들은 수학자들과 과학자들이었습니다. 수학자들은 컴퓨터가 유한한 장치이며, 실수를 정확하게 표현할 수 없다는 사실을 잘 알고 있었습니다. 그래서 수학자들은 수치 해석에 의존하여, 유한한 시스템에서 나온 결과에서 쓸모 있는 결과를 끄집어 내려고 애썼습니다. 과학자들은 노이즈 값이 많은 실험 데이터를 주로 다루었기 때문에 2진 부동소수점 시스템의 부정확성은 그다지 큰 문제가 되지 않았습니다.
더글러스 크락포드 , 『자바스크립트는 왜 그 모양일까?』, 인사이트(2020), p24-25.
Number
생성자는 숫자를 다루기 위해 상수와 메소드를 가지고 있습니다. 다른 타입의 값은Number()
함수를 사용하여 숫자로 바꿀 수 있습니다.
mdn, Number
Number 함수에는 new를 사용해서는 안 됩니다. 여러분들이 원하는 대로 동작하지 않습니다.
const good_example = Number("432"); const bad_example = new Number("432"); typeof good_example // "number" typeof bad_example // "object" good_example === bad_example // false
더글러스 크락포드 , 『자바스크립트는 왜 그 모양일까?』, 인사이트(2020), p17.
C와 같은 전통적인 컴파일 언어를 쓰는 개발자들은 ‘0으로 나누기(Divide By Zero)’ 비슷한 컴파일/런타임 에러를 숱하게 보았을것이다. 그러나 자바스크립트에서는 0으로 나누기 연산이 잘 정의되어 있어서 에러 없이
Infinify
(Number.POSITIVE_INFINITY)라는 결괏값이 나온다.var a = 1 / 0; // Infinity var b = -1 / 0; // -Infinity
카일 심슨 , 『You Don’t Know JS - 타입과 문법, 스코프와 클로저』, 한빛미디어(2017), p56.
NaN은 너무 귀하신 몸이라 다른 어떤 NaN과도 동등하지 않다(즉, 자기 자신과도 같지 않다). 사실상 반사성(Reflective)이 없는 유일무이한 값이다. 따라서 NaN ≠= NaN이다. …비교 결과가 반드시 실패라면 NaN 여부는 어떻게 확인할 수 있을까? …내장 전역 유틸리티 isNaN( ) 함수가 NaN 여부를 말해준다.
카일 심슨 , 『You Don’t Know JS - 타입과 문법, 스코프와 클로저』, 한빛미디어(2017), p54.
isNaN( )는 치명적인 결함이 있다. 이 함수는 NaN(’숫자 아님’)의 의미를 너무 글자 그대로만 해석해서 실제로 ‘인자 값이 숫자인지 여부를 평가’하는 기능이 전부다.
var a = 2 / "foo"; var b = "foo"; a; // NaN b; // "foo" window.isNaN(a); // true window.isNaN(b); // true???
“foo”는 당연히 숫자가 아니지만, 그렇다고 NaN는 아니다! 이 버그는 자바스크립트 탄생 이후 오늘까지 계속됐다. …만약 지금 여러분이 isNaN( ) 를 사용하여 코딩 중이라면, 유감스럽게도 아직 터지지 않은 지뢰(버그)를 묻어놓은 셈이다!
카일 심슨 , 『You Don’t Know JS - 타입과 문법, 스코프와 클로저』, 한빛미디어(2017), p55-56.
var a = 2 / "foo";
var b = "foo";
Number.isNaN(a); // true
Number.isNaN(b); // false
BigInt
는Number
원시 값이 안정적으로 나타낼 수 있는 최대치인 2^53 - 1보다 큰 정수를 표현할 수 있는 내장 객체입니다.
mdn, BigInt
const theBiggestInt = 9007199254740991n;
const alsoHuge = BigInt(9007199254740991); // 9007199254740991n
BigInt
와Number
는 어떤 면에서 비슷하지만 중요한 차이점이 있습니다. 예컨대BigInt
는 내장Math
객체의 메서드와 함께 사용할 수 없고, 연산에서Number
와 혼합해 사용할 수 없습니다. 따라서 먼저 같은 자료형으로 변환해야 합니다. 그러나,BigInt
가Number
로 바뀌면 정확성을 잃을 수 있으니 주의해야 합니다.
mdn, BigInt
References
데이비드 플래너건 , 『자바스크립트 완벽 가이드』, 인사이트(2022)
더글러스 크락포드 , 『자바스크립트는 왜 그 모양일까?』, 인사이트(2020)
카일 심슨 , 『You Don’t Know JS - 타입과 문법, 스코프와 클로저』, 한빛미디어(2017)
이웅모 , 『모던 자바스크립트 Deep Dive』, 위키북스(2020)
mdn - JavaScript data types and data structures