[Deep dive] 21. 빌트인 객체

정호·2023년 5월 6일
0

자바스크립트 객체 분류

표준 빌트인 객체

ECMAScript 사양에 정의된 객체
애플리케이션 전역의 공통 기능을 제공하며 실행 환경과 관계없이 언제나 사용할 수 있다.
별도의 선언없이 전역 변수 없이 참조 가능

호스트 객체

ECMAScript 사양에 정의되어 있지 않은 객체
자바스크립트 실행 환경에서 추가로 제공하는 객체(브라우저 환경 or Node.js 환경)
브라우저: DOM,BOM,Canvas,fetch ...
Node.js: Node.js고유의 API를 호스트 객체로 제공

사용자 정의 객체

기본 제공되는 객체가 아닌 사용자가 직접 정의한 객체


표준 빌트인 객체

Object, String, Number, Function, Reflect, Promise, Proxy 등 40여개 제공

  • Math, Reflect, JSON을 제외한 표준 빌트인 객체는 인스턴스를 생성할 수 있는 생성자 함수 객체
    프로토타입 메서드와 정적 메서드 제공 / 정적 메서드만 제공
// String 생성자 함수에 의한 String 객체 생성
const strObj = new String('Lee'); // String {"Lee"}
console.log(typeof strObj);       // object

// Number 생성자 함수에 의한 Number 객체 생성
const numObj = new Number(123); // Number {123}
console.log(typeof numObj);     // object

// Boolean 생성자 함수에 의한 Boolean 객체 생성
const boolObj= new Boolean(true); // Boolean {true}
console.log(typeof boolObj);      // object

// Function 생성자 함수에 의한 Function 객체(함수) 생성
const func = new Function('x', 'return x * x'); // ƒ anonymous(x )
console.log(typeof func);                       // function

// Array 생성자 함수에 의한 Array 객체(배열) 생성
const arr = new Array(1, 2, 3); // (3) [1, 2, 3]
console.log(typeof arr);        // object

// RegExp 생성자 함수에 의한 RegExp 객체(정규 표현식) 생성
const regExp = new RegExp(/ab+c/i); // /ab+c/i
console.log(typeof regExp);         // object

// Date 생성자 함수에 의한 Date 객체 생성
const date = new Date();  // Fri May 08 2020 10:43:25 GMT+0900 (대한민국 표준시)
console.log(typeof date); // object

예시

생성자 함수인 표준 빌트인 객체가 생성한 인스턴스의 프로토타입은 표준 빌트인 객체의 prototype 프로퍼티에 바인딩된 객체
-> String을 생성자 함수로서 호출하여 생성한 String인스턴스의 프로토타입은 String.prototype
표준 빌트인 객체의 prototype 프로퍼티에 바인딩된 객체는 다양한 기능의 빌트인 프로토타입 메서드를 제공

// String 생성자 함수에 의한 String 객체 생성
const strObj = new String('Lee'); // String {"Lee"}

// String 생성자 함수를 통해 생성한 strObj 객체의 프로토타입은 String.prototype이다.
console.log(Object.getPrototypeOf(strObj) === String.prototype); // true

Number 생성자 예제

// Number 생성자 함수에 의한 Number 객체 생성
const numObj = new Number(1.5); // Number {1.5}

// toFixed는 Number.prototype의 프로토타입 메서드다.
// Number.prototype.toFixed는 소수점 자리를 반올림하여 문자열로 반환한다.
console.log(numObj.toFixed()); // 2

// isInteger는 Number의 정적 메서드다.
// Number.isInteger는 인수가 정수(integer)인지 검사하여 그 결과를 Boolean으로 반환한다.
console.log(Number.isInteger(0.5)); // false

원시값과 래퍼 객체

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

const str = 'hello';

// 원시 타입인 문자열이 프로퍼티와 메서드를 갖고 있는 객체처럼 동작한다.
console.log(str.length); // 5
console.log(str.toUpperCase()); // HELLO
  • 원시값에 대해 객체처럼 마침표표기법으로 접근하면 자바스크립트 엔진이 객체로 변환해줌
    이 임시 객체를 래퍼 객체라고 한다.
const str = 'hi';

// 원시 타입인 문자열이 래퍼 객체인 String 인스턴스로 변환된다.
console.log(str.length); // 2
console.log(str.toUpperCase()); // HI

// 래퍼 객체로 프로퍼티에 접근하거나 메서드를 호출한 후, 다시 원시값으로 되돌린다.
console.log(typeof str); // string

이때 문자열 래퍼 객체인 String 생성자 함수의 인스턴스는 String.prototype의 메서드를 상속받아 사용
-> 래퍼 객체의 처리가 종료되면 래퍼 객체의 [[StringData]] 내부 슬롯에 할당된 원시값으로 돌리고 래퍼 객체는 갈비지 컬렉션의 대상이 된다.

// ① 식별자 str은 문자열을 값으로 가지고 있다.
const str = 'hello';

// ② 식별자 str은 암묵적으로 생성된 래퍼 객체를 가리킨다.
// 식별자 str의 값 'hello'는 래퍼 객체의 [[StringData]] 내부 슬롯에 할당된다.
// 래퍼 객체에 name 프로퍼티가 동적 추가된다.
str.name = 'Lee';

// ③ 식별자 str은 다시 원래의 문자열, 즉 래퍼 객체의 [[StringData]] 내부 슬롯에 할당된 원시값을 갖는다.
// 이때 ②에서 생성된 래퍼 객체는 아무도 참조하지 않는 상태이므로 가비지 컬렉션의 대상이 된다.

// ④ 식별자 str은 새롭게 암묵적으로 생성된(②에서 생성된 래퍼 객체와는 다른) 래퍼 객체를 가리킨다.
// 새롭게 생성된 래퍼 객체에는 name 프로퍼티가 존재하지 않는다.
console.log(str.name); // undefined

// ⑤ 식별자 str은 다시 원래의 문자열, 즉 래퍼 객체의 [[StringData]] 내부 슬롯에 할당된 원시값을 갖는다.
// 이때 ④에서 생성된 래퍼 객체는 아무도 참조하지 않는 상태이므로 가비지 컬렉션의 대상이 된다.
console.log(typeof str, str);

전역 객체

코드가 실행되기 이전 어떤 객체보다 먼저 생성되는 어디에도 속하지 않는 최상위 객체
브라우저 환경에서는 window, Node.js는 global

객체의 계층적 구조상 표준 빌트인 객체와 호스트 객체를 프로퍼티로 소유한다는 것

  • 전역 객체는 의도적으로 생성할 수 없다. 즉 전역 객체를 생성할 수 있는 생성자 함수는 없다.
  • 전역 객체의 프로퍼티를 참조할 때 window를 생략할 수 있다.
// var 키워드로 선언한 전역 변수
var foo = 1;
console.log(window.foo); // 1

// 선언하지 않은 변수에 값을 암묵적 전역. bar는 전역 변수가 아니라 전역 객체의 프로퍼티다.
bar = 2; // window.bar = 2
console.log(window.bar); // 2

// 전역 함수
function baz() { return 3; }
console.log(window.baz()); // 3
  • let, const 키워드로 선언한 전역 변수는 전역 객체의 프로퍼티가 아니다.
    -> winodow.foo와 같이 접근할 수 없다.

빌트인 전역 프로퍼티

빌트인 전역 프로퍼티는 전역 객체의 프로퍼티를 의미한다. 전역에서 사용하는 값 제공

Infinity

무한대를 나타내는 숫자 값
// 전역 프로퍼티는 window를 생략하고 참조할 수 있다.
console.log(window.Infinity === Infinity); // true

// 양의 무한대
console.log(3/0);  // Infinity
// 음의 무한대
console.log(-3/0); // -Infinity
// Infinity는 숫자값이다.
console.log(typeof Infinity); // number

NaN

숫자가 아님을 나타내는 숫자값 NaN을 갖는다.

console.log(window.NaN); // NaN

console.log(Number('xyz')); // NaN
console.log(1 * 'string');  // NaN
console.log(typeof NaN);    // number

undefined

console.log(window.undefined); // undefined

var foo;
console.log(foo); // undefined
console.log(typeof undefined); // undefined

빌트인 전역 프로퍼티

전역에서 호출할 수 있는 빌트인 함수, 전역 객체의 메서드

eval

자바스크립트 코드를 나타내는 문자열을 인수로 전달
표현식이면 eval 함수는 문자열 코드를 런타임에 평가하여 값을 생성
문이면 eval 함수는 문자열 코드를 런타임에 실행

// 표현식인 문
eval('1 + 2;'); // -> 3
// 표현식이 아닌 문
eval('var x = 5;'); // -> undefined

// eval 함수에 의해 런타임에 변수 선언문이 실행되어 x 변수가 선언되었다.
console.log(x); // 5

// 객체 리터럴은 반드시 괄호로 둘러싼다.
const o = eval('({ a: 1 })');
console.log(o); // {a: 1}

// 함수 리터럴은 반드시 괄호로 둘러싼다.
const f = eval('(function() { return 1; })');
console.log(f()); // 1

isFinite

전달받은 인수가 정상적인 유한수인지 검사 true/false
NaN이면 false

// 인수가 유한수이면 true를 반환한다.
isFinite(0);    // -> true
isFinite(2e64); // -> true
isFinite('10'); // -> true: '10' → 10
isFinite(null); // -> true: null → 0

// 인수가 무한수 또는 NaN으로 평가되는 값이라면 false를 반환한다.
isFinite(Infinity);  // -> false
isFinite(-Infinity); // -> false

// 인수가 NaN으로 평가되는 값이라면 false를 반환한다.
isFinite(NaN);     // -> false
isFinite('Hello'); // -> false
isFinite('2005/12/12'); // -> false

isNaN

전달받은 인수가 NaN인지 검사 true/false

// 숫자
isNaN(NaN); // -> true
isNaN(10);  // -> false

// 문자열
isNaN('blabla'); // -> true: 'blabla' => NaN
isNaN('10');     // -> false: '10' => 10
isNaN('10.12');  // -> false: '10.12' => 10.12
isNaN('');       // -> false: '' => 0
isNaN(' ');      // -> false: ' ' => 0

// 불리언
isNaN(true); // -> false: true → 1
isNaN(null); // -> false: null → 0

// undefined
isNaN(undefined); // -> true: undefined => NaN

// 객체
isNaN({}); // -> true: {} => NaN

// date
isNaN(new Date());            // -> false: new Date() => Number
isNaN(new Date().toString()); // -> true:  String => NaN

암묵적 전역

var x = 10; // 전역 변수

function foo () {
 // 선언하지 않은 식별자에 값을 할당
 y = 20; // window.y = 20;
}
foo();

// 선언하지 않은 식별자 y를 전역에서 참조할 수 있다.
console.log(x + y); // 30

foo 함수 내의 y는 선언하지 않은 식별자 -> y = 20 참조 에러
❖ 하지만 전역 변수처럼 동작하는 이유는
선언하지 않은 식별자에 값을 할당하면 전역 객체의 프로퍼티가 되기 때문

  • foo 함수가 호출되면 자바스크립트 엔진은 y 변수에 값을 할당하기 위해 스코프 체인을 통해 선언된 변수인지 확인 -> 찾을 수 없으므로 에러
  • y = 20, window.y = 20을 해석하여 동적 생성(변수 선언 없이 전역 객체의 프로퍼티로 추가되었을 뿐이라 변수 호이스팅이 발생하지 않음)
    암묵적 전역
profile
열심히 기록할 예정🙃

0개의 댓글