자바스크립트는 Object
, String
, Number
, Date
, Math
, RegExp
, Array
, Map
, Set
, Promise
, Reflect
, Proxy
, JSON
, Error
등 40여 개의 표준 빌트인 객체를 제공한다.
Math
, Reflect
, JSON
을 제외한 표준 빌트인 객체는 모두 인스턴스를 생성할 수 있는 생성자 함수 객체다.
const strObj = new String('Lee'); // String {"Lee"}
console.log(typeof strObj); // object
const numObj = new Number(123); // Number {123}
console.log(typeof numObj); // object
const func = new Function('x', 'return x * x'); // f anonymous(x) { return x * x }
console.log(typeof func); // object
const regExp = new RegExp(/ab+c/i); // /ab+c/i
console.log(typeof regExp); // object
const date = new Date(); // Mon Jul 05 2021 14:12:22 GMT+0900 (대한민국 표준시)
console.log(typeof date); // object
표준 빌트인 객체가 생성한 인스턴스의 프로토타입은 표준 빌트인 객체의 prototype
프로퍼티에 바인딩된 객체다. 예를 들어, String
인스턴스의 프로토타입은 String.prototype
이다.
prototype
프로퍼티에 바인딩된 객체는 다양한 기능의 빌트인 프로토타입 메서드를 제공한다.
const numObj = new Number(1.5); // Number {1.5}
// 소수점 자리를 반올림하여 그 결과를 반환한다.
console.log(numObj.toFixed()); // 2
// 정수인지 검사하여 그 결과를 반환한다.
console.log(Number.isInteger(0.5)); // false
문자열이나 숫자 등의 원시값이 있는데도 문자열, 숫자 등의 표준 빌트인 생성자 함수가 존재하는 이유는 무엇일까? 다음의 예제를 살펴보자.
const str = 'hello';
console.log(str.length); // 5
console.log(str.toUpperCase()); // HELLO
console.log(typeof str); // string
원시 값은 객체가 아니기 때문에 프로퍼티나 메서드를 가질 수 없는데도 불구하고, 원시 타입인 문자열 str
이 프로퍼티와 메서드를 갖고 있는 객체처럼 동작하는 것을 알 수 있다.
이는 원시값인 문자열, 숫자, 불리언 값의 경우에 마침표 또는 대괄호 표기법으로 접근하면 자바스크립트 엔진이 일시적으로 원시값을 연관된 객체로 변환해주기 때문이다.
자바스크립트 엔진은 원시값을 객체처럼 사용하면 암묵적으로 연관된 객체를 생성해서, 생성된 객체로 프로퍼티에 접근하거나 메서드를 호출하고 다시 원시 값으로 되돌린다.
문자열, 숫자, 불리언 값에 대해 객체처럼 접근하면 생성되는 임시 객체를 래퍼 객체(wrapper object) 라 한다.
이처럼 래퍼 객체에 의해 문자열, 숫자, 불리언은 마치 객체처럼 사용할 수 있고 표준 빌트인 객체의 프로토타입 메서드 또는 프로퍼티를 참조할 수 있다. 그렇기 때문에 String, Number, Boolean 생성자 함수를 new 연산자와 함께 호출하여 문자열, 숫자, 불리언 인스턴스를 생성할 필요가 없으며 권장하지도 않는다.
전역 객체(global object) 는 코드가 실행되기 이전에 자바스크립트 엔진에 의해 어떤 객체보다도 먼저 생성되는 객체이며, 어떤 객체에도 속하지 않는 최상위 객체이다.
전역 객체는 자바스크립트 환경에 따라 지칭하는 이름이 다르다. 브라우저 환경에서는 window
(또는 self, this, frames)이지만 Node.js 환경에서는 global
이다.
전역 객체가 갖고 있는 프로퍼티는 다음과 같다.
var
키워드로 선언한 전역 변수와 전역 함수var foo = 1;
console.log(window.foo); // 1
function baz() { return 3; }
console.log(window.baz()); // 3
전역 객체의 프로퍼티를 참조할 때는 window
를 생략할 수 있다.
// 문자열 'F'를 16진수로 해석하여 10진수로 변환
window.parseInt('F', 16); // 15
parseInt('F', 16); // 15
window.parseInt === parseInt; // true
전역 객체는 몇 가지 프로퍼티와 메서드를 가지고 있다. 이에 대해 살펴보자.
전역 객체의 프로퍼티를 말하며, 주로 애플리케이션 전역에서 사용하는 값을 제공한다. 전역 프로퍼티 중에 몇 가지만 살펴보자.
Infinity
프로퍼티는 무한대를 나타내는 숫자값 Infinity를 갖는다.
console.log(Infinity); // Infinity
// 양의 무한대
console.log(3/0); // Infinity
// 음의 무한대
console.log(-3/0); // -Infinity
// Infinity는 숫자값이다.
console.log(typeof Infinity); // number
NaN
프로퍼티는 숫자가 아님(Not-a-Number)을 나타내는 숫자값 NaN을 갖는다. NaN
프로퍼티는 Number.NaN
프로퍼티와 같다.
console.log(NaN); // NaN
console.log(Number('xyz')); // NaN
console.log(1 * 'string'); // NaN
// NaN는 숫자값이다.
console.log(typeof NaN); // number
undefined
프로퍼티는 원시 타입 undefined를 값으로 갖는다.
console.log(window.undefined); // undefined
var foo;
console.log(foo); // undefined
console.log(typeof undefined); // undefined
애플리케이션 전역에서 호출할 수 있는 빌트인 함수로서, 전역 객체의 메서드다. 제공하고 있는 빌트인 전역 함수 중에 몇 가지만 간략하게 살펴보자.
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
함수는 보안에 취약할 뿐만 아니라 또한 eval
함수를 통해 실행되는 코드는 자바스크립트 엔진에 의해 최적화가 수행되지 않아 일반적인 코드 실행에 비해 처리 속도가 느리기에, eval
함수는 사용하지 않는 것이 좋다.
전달받은 인수가 NaN인지 검사하여 그 결과를 불리언 타입으로 반환한다. 전달받은 인수의 타입이 숫자가 아닌 경우 숫자로 타입을 변환한 후 검사를 수행한다.
isNaN(NaN); // true
isNaN(10); // false
isNaN('10'); // false '10' => 10
isNaN(''); // false '' => 0
isNaN(true); // false true => 1
isNaN(null); // false null => 0
isNaN(undefined); // true
isNaN({}); // true
isNaN(new Date()); // false new Date() => Number
isNaN(new Date().toString()); // true String => NaN
URI(Uniform Resource Identifier)는 인터넷에 있는 자원을 나타내는 주소를 말한다. URI의 하위 개념으로 URL, URN이 있다.
URI 구조 / 그림출처: poiemaweb
encodeURI
함수는 URI를 문자열로 전달받아 인코딩을, decodeURI
함수는 인코딩된 URI를 인수로 전달받아 디코딩한다.
인코딩이란 URI 문자들을 ASCII 문자 셋으로 변환하는 것을 의미한다. 예를 들어 특수 문자인 공백 문자는 %20
, 한글 '가'는 %EC%9E%90
으로 인코딩된다.
const uri = 'http://example.com?name=홍길동&job=programmer';
const enc = encodeURI(uri);
console.log(enc); // http://example.com?name=%ED%99%8D%EA%B8%B8%EB%8F%99&job=programmer
const dec = decodeURI(enc);
console.log(dec); // http://example.com?name=홍길동&job=programmer
encodeURIComponent
함수는 URI 구성 요소를 인수로 전달받아 인코딩한다. 인수로 전달된 문자열을 쿼리 스트링의 일부로 간주하여, 쿼리스트링 구분자로 사용되는 =
, ?
, &
까지 인코딩한다.
반면 encodeURI
함수는 매개변수로 전달된 문자열을 완전한 URI 전체라고 간주해 쿼리 스트링 구분자는 인코딩하지 않는다.
decodeURIComponent
함수는 매개변수 전달된 URI 구성 요소를 디코딩한다.
const uriComp = '홍길동&job=programmer';
let enc = encodeURIComponent(uriComp);
console.log(enc); // %ED%99%8D%EA%B8%B8%EB%8F%99%26job%3Dprogrammer
let dec = decodeURIComponent(enc);
console.log(dec); // 홍길동&job=programmer
enc = encodeURI(uriComp);
console.log(enc); // %ED%99%8D%EA%B8%B8%EB%8F%99&job=programmer
dec = decodeURI(enc);
console.log(dec); // 홍길동&job=programmer