notes
21장. 빌트인 객체
모던 JS Deep Dive — 빌트인 객체의 종류·기능과 활용 핵심 정리.
참고: 이웅모 《모던 자바스크립트 Deep Dive》 21장 · [MDN Standard built-in objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects) · [MDN Global object](https://developer.mozilla.org/en-US/docs/Glossary/Global_object)
'hello'.toUpperCase()가 되는 순간 “원시인데 메서드?”에서 멈췄다.
빌트인 객체·래퍼·전역 객체를 한 지도에 올려야 이 마법이 풀린다. 이 장은 “이미 엔진이 깔아 둔 도구들”과 “로비(전역)에 뭐가 올라가 있는지”다.
flowchart TB
OBJ[JS 객체] --> STD[표준 빌트인]
OBJ --> HOST[호스트: DOM/Node API 등]
OBJ --> USER[사용자 정의]
PRIM[원시값] -->|프로퍼티 접근| WRAP[일시 래퍼 객체]
WRAP --> PRIM2[다시 원시]
G[전역 객체] --> PROP[Infinity / NaN / globalThis …]
G --> FN[parseInt / eval / isNaN …]
21.1 객체의 분류 (감각)
대략 세 갈래로 나누면 머리가 맑다.
- 표준 빌트인 객체 — ECMAScript가 정한
Object,Array,String,Promise… - 호스트 객체 — 실행 환경이 제공. 브라우저
Document/HTMLElement, Nodeprocess/Buffer등 - 사용자 정의 객체 — 내가 리터럴·생성자·class로 만든 것
표준 빌트인은 전역 객체의 프로퍼티로 미리 올라가 있어 별도 import 없이 쓴다.
21.2 표준 빌트인 객체
생성자 함수 형태가 많다: Object, String, Number, Boolean, Symbol, Date, RegExp, Array, Map, Set, WeakMap, WeakSet, Function, Promise, Error 계열…
정적 메서드만 있는 느낌의 것도 있다: Math, JSON, Reflect, Atomics…
console.log(typeof Object); // function — 생성자이자 함수 객체
console.log(typeof Math); // object — Math는 생성자가 아님
console.log(new Date());
console.log(JSON.stringify({ a: 1 }));
WHY: “전부 new로 만든다”가 아니다. Math에 new를 붙이면 실패한다. 문서를 보고 생성자인지 네임스페이스인지 구분한다.
21.3 원시값과 래퍼 객체
문자열·숫자·불리언 원시에는 프로퍼티가 없는데, str.length / str.toUpperCase()가 된다. 엔진이 일시적으로 래퍼 객체(String/Number/Boolean 인스턴스)를 만들어 메서드를 호출한 뒤, 그 래퍼는 버려지고 다시 원시로 남는다.
const str = 'hello';
console.log(str.length); // 5
console.log(str.toUpperCase()); // HELLO
console.log(typeof str); // 여전히 'string'
명시적으로 new String('hello')를 만들 수는 있으나 권장하지 않는다. typeof가 'object'가 되고, 동등 비교가 꼬인다.
const s1 = 'hi';
const s2 = new String('hi');
console.log(typeof s1, typeof s2); // string object
console.log(s1 == s2); // true (강제 변환)
console.log(s1 === s2); // false
WHY: 래퍼는 “원시에 메서드를 빌려 주는 순간”의 구현 디테일이다. 일상 코드는 원시를 쓰고, 래퍼 생성자는 거의 안 탄다.
숫자·불리언도 같다: (1.234).toFixed(2), true.toString().
심벌·BigInt도 메서드를 가지지만 new Symbol()은 불가(팩토리 Symbol()).
21.4 전역 객체
환경의 최상위 객체. 브라우저 window(프레임에선 self 등), Worker self, Node global. 통합 접근자는 `globalThis`.
특징 감각:
- 전역 변수(
var)·전역 함수가 프로퍼티로 붙는 경로가 있다(환경·키워드에 따라 다름) - 표준 빌트인도 여기 프로퍼티
window를 생략하고parseInt,Infinity처럼 쓸 수 있는 이유가 전역 객체 식별자 생략 규칙
console.log(globalThis === window); // 브라우저 메인 스레드에서 대개 true
console.log(globalThis.Math === Math);
21.4.1 빌트인 전역 프로퍼티
자주 쓰는 값들:
Infinity/-InfinityNaNundefined(식별자이자 전역 프로퍼티로 존재할 수 있음 — 재할당 이슈는 옛 환경 이야기)
console.log(3 / 0); // Infinity
console.log(Number('x')); // NaN
console.log(NaN === NaN); // false — 비교는 Number.isNaN
21.4.2 빌트인 전역 함수
대표:
eval— 문자열을 코드로. 쓰지 않는 쪽이 기본(보안·최적화·가독성)isNaN/isFinite— 약한 강제 변환 있음 → 모던 코드는Number.isNaN/Number.isFiniteparseInt/parseFloat— 문자열 → 수.parseInt('08')옛 옥탈 이슈는 모던 엔진에선 완화, radix 명시가 안전- URI 계열:
encodeURI/decodeURI/encodeURIComponent/decodeURIComponent
console.log(parseInt('10', 10));
console.log(parseInt('10px', 10)); // 10 — 뒤 쓰레기 허용
console.log(Number('10px')); // NaN — 더 엄격
console.log(isNaN('foo')); // true (숫자로 강제 후)
console.log(Number.isNaN('foo')); // false
console.log(Number.isNaN(NaN)); // true
const q = encodeURIComponent('a=1&b=안녕');
WHY: “전역 함수니까 그냥 쓴다”보다 어느 쪽이 강제 변환을 덜 하는지를 고른다.
21.4.3 암묵적 전역
선언 없이 할당하면(슬롭) 전역 객체의 프로퍼티가 생긴다. 14·20장과 직결. strict·모듈에서는 ReferenceError.
function f() {
// leaked = 1; // 슬롭: 전역 프로퍼티 / strict: ReferenceError
}
표
예제 — 왜 이렇게 쳐 봤냐
// 입력 파싱: Number vs parseInt
function toId(raw) {
const n = Number(raw);
if (!Number.isFinite(n)) throw new Error('bad id');
return n;
}
// URI
const url = `https://ex.com/search?q=${encodeURIComponent(userQuery)}`;
// 래퍼 함정 피하기
const ok = 'hi';
const bad = new String('hi');
console.log(ok === 'hi'); // true
console.log(bad === 'hi'); // false
헷갈리던 장면 / 함정
new Number(0)는 truthy 객체 —if (new Number(0))가 참parseIntvsNumber혼용isNaNvsNumber.isNaNeval로 설정 파싱- 전역에 도메인 상태 부착 (14)
- Worker/Node에서
window가정
질문 → 자답
Q. Math는 왜 new가 안 되나? A. 네임스페이스 객체. 정적 함수 모음.
Q. 래퍼를 변수에 보관하면?
A. 명시 new String과 같이 객체가 남는다. 일시 래퍼는 표현식 평가 후 사라지는 쪽에 가깝다.
Q. globalThis 이전에는?
A. 환경별 window/self/global 분기. 지금은 globalThis 우선.
웹 보강 메모
MDN Global Objects 목록을 훑고, 레포에서 isNaN( / parseInt( / new String / new Number 사용을 검색해 교체 후보를 표시했다.
실무로 바로
- 원시 유지, 래퍼 생성자 금지
- NaN 검사:
Number.isNaN - 정수 파싱:
Number.parseInt(str, 10)또는Number - 전역 상태 금지, 빌트인만 전역에서 소비
- 크로스 런타임:
globalThis
여기서 잠깐 💁♂️
22장은 this. 전역 객체는 “일반 함수 this가 슬롭에서 어디로 붙는지”의 도착지다. strict는 그걸 undefined로 끊는다(20).