[딥다이브] 21. 빌트인 객체

codeyun2 2024. 6. 4. 01:48

21.1 자바스크립트 객체의 분류

  • 표준 빌트인 객체(standard built-in objects/native objects/global objects)
    ECMAScript 사양에 정의된 객체
    애플리케이션 전역에 공통 기능을 제공
    자바스크립트 실행 환경(브라우저/Node.js)에 관계없이 언제나 사용할 수 있음
    전역 객체의 프로퍼티로 제공되어 언제나 참조할 수 있음
  • 호스트 객체(host objects)
    ECMAScript 사양에 정의되어 있지 않음
    자바스크립트 실행 환경에서 추가로 제공하는 객체
    • 브라우저 환경: DOM, BOM, Canvas, XMLHttpRequest, fetch, requestAnimationFrame, SVG, Web Storage, Web Component, Web Worker 등 클라이언트 사이드 Web API
    • Node.js 환경: Node.js 고유 API
  • 사용자 정의 객체
    사용자가 직접 정의한 객체

 

21.2 표준 빌트인 객체

Object, String, Number, Boolean, Symbol, Date, Math, RegExp, Array, Map/Set, WeakMap/WeakSet, Function, Promise, Reflect, Proxy, JSON, Error 등 40여 개

 

Math, Reflect, JSON을 제외한 표준 빌트인 객체는 모두 인스턴스를 생성할 수 있는 생성자 함수 객체

정적 메서드만 제공 ↔ 프로토타입 메서드와 정적 메서드 제공

 

21.3 원시값과 래퍼 객체

문자열, 숫자, 불리언 등의 원시값이 있는데

문자열, 숫자, 불리언 객체를 생성하는 String, Number, Boolean 등의 표준 빌트인 생성자 함수가 존재하는 이유

 

 

원시값은 객체가 아니어서 프로퍼티나 메서드를 가질 수 없음

 

원시값에 객체처럼 접근하면

자바스크립트 엔진이 암묵적으로 연관된 객체를 생성(래퍼 객체wrapper object)하고

다시 원시값으로 되돌림(이 때 래퍼 객체는 가비지 컬렉션의 대상이 됨)

 

string에 객체처럼 접근하면 래퍼 객체는 String 생성자 함수의 인스턴스, string은 [[StringData]] 내부 슬롯에 할당됨

암묵적으로 생성되는 래퍼 객체에 의해 원시값들을 객체처럼 사용할 수 있음

원시값을 생성자 함수로 생성하는 것은 권장하지 않음

 

Symbol은 생성자 함수가 아님

원시값 null과 undefined는 래퍼 객체를 생성하지 않기 때문에 객체처럼 접근하면 에러 발생

 

21.4 전역 객체

코드가 실행되기 이전 단계에 자바스크립트 엔진에 의해 어떤 객체보다도 먼저 생성되는 특수한 객체, 최상위 객체

브라우저 환경: window(self, this, frames)

Node.js: global

 

globalThis: ECMAScript2020에서 도입, 환경별로 다른 식별자를 통일한 식별자. ECMAScript 표준 사양을 준수하는 모든 환경에서 사용할 수 있음

// 브라우저 환경
globalThis === this
globalThis === window
globalThis === self
globalThis === frames

// Node.js 환경(12.0.0 이상)
globalThis === this
globalThis === global

 

전역 객체는 최상위 객체로

표준 빌트인 객체, 호스트 객체, 사용자 정의 전역 변수/함수를 프로퍼티로 가짐

다른 객체에 소유되지 않음

프로토타입 상속 관계상 최상위 객체는 아님

  • 개발자가 의도적으로 생성할 수 없음(생성자 함수 없음)
  • 전역 객체의 프로퍼티를 참조할 때 식별자(window/global)를 생략할 수 있음(window.parseInt === parseInt)
  • let / const 키워드로 선언한 전역 변수는 보이지 않는 개념적 블록 내에 존재하여 전역 객체의 프로퍼티가 아님
    (23. 실행 컨텍스트에서 계속) 
  • 브라우저 환경의 모든 자바스크립트 코드는 하나의 전역 객체를 공유(여러 script 태그가 있어도)
    = 분리되어 있는 자바스크립트 코드가 하나의 전역 객체를 공유

 

1. 빌트인 전역 프로퍼티

Infinity 무한대를 나타내는 숫자값
NaN 숫자가 아님을 나타내는 숫자값(Not a Number)
Number.NaN과 같음
undefined undefined

 

2. 빌트인 전역 함수

- eval

자바스크립트 코드를 나타내는 문자열을 인수로 전달받아

표현식이라면 런타임에 평가하여 값을 생성,

표현식이 아닌 문이라면 런타임에 실행

eval('1 + 2;'); // 3
eval('var x = 5;'); // undefined
console.log(x); // 5

// 객체/함수 리터럴은 괄호로 감싸야함
const o = eval('({ a: 1})'); 
console.log(o); // { a: 1 }

const f = eval('(function() { return 1; })'); 
console.log(f()); // 1

 

인수로 전달받은 문자열 코드가 여러 개의 문으로 구성되어 있다면 마지막 결과값을 반환

eval('1 + 2; 3 + 4;') // 7

 

기존의 스코프를 런타임에 동적으로 수정(함수 객체 스코프)

 

strict mode에서는 자체 스코프를 생성

let / const 사용한 변수 선언문은 암묵적으로 strict mode가 적용됨

 

보안에 취약하기 때문에 사용 금지

eval을 통해 실행되는 코드는 자바스크립트 엔진에 의해 최적화가 수행되지 않으므로 처리 속도가 느림

 

- isFinite

유한수: true

무한수(+ NaN값): false

전달받은 인수의 타입이 숫자가 아닌 경우 숫자로 타입 변환 후 검사

 

- isNaN

전달받은 인수가 NaN인지 검사하여 boolean 리턴

전달받은 인수의 타입이 숫자가 아닌 경우 숫자로 타입 변환 후 검사

isNaN(undefined); // true
Number.isNaN(undefined); // false

 

- parseFloat

전달받은 문자열을 부동 소수점 숫자(floating point number 실수)로 해석하여 반환

 

- parseInt(문자열, 기수)

전달받은 문자열을 기수의 숫자로 해석하여 정수(integer) 반환

문자열을 전달받은 기수로 해석할 수 없다면 NaN 반환

10진수 숫자를 진법 변환하고 싶을 경우 Number.prototype.toString 메서드 사용

 

16진수 리터럴은 지수를 생략해도 해석

2진수, 8진수 리터럴은 제대로 해석하지 못함

 

- encodeURI

URI(Uniform Resource Identifier)를 문자열로 전달받아 인코딩

= 이스케이프 처리

= 아스키 문자 셋으로 변환하는 것

 

URI 문법 형식 표준 RFC3986

URL은 아스키 문자 셋으로만 구성되어야 함

한글 포함 대부분 외국어, 아스키 문자 셋에 정의되지 않은 특수문자가 포함된 경우 문제 예방을 위해 이스케이프 처리 필요

허용: 알파벳, 0~9, - _ . ! ~ * ' ( )

이스케이프: % ? #(URL), 한글, 공백 등, < >(시스템에 의해 해석될 수 있는 문자)

 

- decodeURI

인코딩된 URI를 전달받아 이스케이프 처리 이전으로 디코딩

 

- encodeURIComponent

URI 구성 요소를 인수로 전달받아 인코딩

전달받은 문자열을 쿼리 스트링의 일부로 간주하여 = ? &까지 인코딩

↔ encodeURI는 = ? &를 인코딩하지 않음

 

- decodeURIComponent

URI 구성 요소를 디코딩

 

3. 암묵적 전역

전역 객체의 프로퍼티로 추가됨

변수가 아니기 때문에 변수 호이스팅이 발생하지 않음, delete로 삭제할 수 있음

전역 변수(x)는 전역 객체의 프로퍼티이지만 delete 연산자로 삭제할 수 없음

console.log(x); // undefined
console.log(y); // ReferenceError: y is not defined

var x = 10;

function foo () {
  y = 20; // window.y = 20
  console.log(x + y); // 30
}

foo(); // 30

console.log(window.x); // 10
console.log(window.y); // 20

delete x; // false
delete y; // true

console.log(window.x); // 10
console.log(window.y); // undefined