21장 빌트인 객체
자바스크립트 객체의 분류
- 표준 빌트인 객체 : ECMAScript 사양에 정의. 앱 전역의 공통 기능 제공. 별도 선언 없이 전역 변수처럼 언제나 참조 가능.
- 호스트 객체 : ECMAScript 사양에 정의x. 자바스크립트 실행환경(브라우저)에서 추가로 제공하는 객체.
- 사용자 정의 객체 : 표준 빌트인 객체와 호스트 객체처럼 기본 제공되는 객체가 아님. 사용자가 직접 정의한 객체
표준 빌트인 객체
- Object, String, Number, Boolean, Symbol, Date, Math, Array, …
- 인스턴스를 생성할 수 있는 생성자 함수 객체.(Math, Reflect, JSON 제외)
- 프로토타입 메서드, 정적 메서드를 제공.
생성자 함수로 호출하여 인스턴스 생성 가능
21-01
// 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 프로퍼티에 바인딩된 객체다.
ex) String을 생성자 함수로 호출하여 생성한 String 인스턴스의 프로토타입은 String.prototype
21-02
// String 생성자 함수에 의한 String 객체 생성
const strObj = new String('Lee'); // String {"Lee"}
// String 생성자 함수를 통해 생성한 strObj 객체의 프로토타입은 String.prototype이다.
console.log(Object.getPrototypeOf(strObj) === String.prototype); // true
- 표준 빌트인 객체의 prototype 프로퍼티에 바인딩된 객체(ex. String.prototype)는 다양항 기능의 빌트인 프로토타입 메서드를 제공함.
- 표준 빌트인 객체는 인스턴스 없이도 호출 가능한 빌트인 정적 메서드를 제공함.
ex) Number의 prototype 프로퍼티에 바인딩된 객체 Number.prototype는 다양한 기능의 빌트인 프로토타입 메서드를 제공함.
21-03
// 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 표준 빌트인 생성자 함수가 존재하는 이유는 뭘까?
원시값은 객체가 아니므로 프로퍼티나 메서드를 가질 수 없는데도 원시값인 문자열이 마치 객체처럼 동작함.
21-04
const str = 'hello';
// 원시 타입인 문자열이 프로퍼티와 메서드를 갖고 있는 객체처럼 동작한다.
console.log(str.length); // 5
console.log(str.toUpperCase()); // HELLO
- 원시값에 대해 객체처럼 마침표 표기법으로 접근하면 JS엔진이 일시적으로 원시값을 연관된 객체로 변환해줌.
- 문자열, 숫자, 불리언 값에 대해 객체처럼 접근하면 생성되는 임시객체 : 래퍼 객체
21-05
const str = 'hi';
// 원시 타입인 문자열이 래퍼 객체인 String 인스턴스로 변환된다.
console.log(str.length); // 2
console.log(str.toUpperCase()); // HI
// 래퍼 객체로 프로퍼티에 접근하거나 메서드를 호출한 후, 다시 원시값으로 되돌린다.
console.log(typeof str); // string
과정
21-06
// ① 식별자 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);
과정
21-07
const num = 1.5;
// 원시 타입인 숫자가 래퍼 객체인 Number 객체로 변환된다.
console.log(num.toFixed()); // 2
// 래퍼 객체로 프로퍼티에 접근하거나 메서드를 호출한 후, 다시 원시값으로 되돌린다.
console.log(typeof num, num); // number 1.5
- 문자열, 숫자, 불리언, 심벌은 String, Number, Boolean, Symbol의 프로토타입 메서드 또는 프로퍼티를 참조할 수 있음.⇒ String, Number, Boolean 생성자 함수를 new 연산자와 함께 호출할 필요 없음.
- null, undefined는 래퍼 객체 생성 x.⇒ null.abc undefined.abc 처럼 사용하면 에러가 발생.
전역 객체
- 코드 실행 이전 단계에 가장 먼저 생성되는 특수한 객체. 최상위 객체.
- JS 환경에 따라 이름이 다름.
- 브라우저 환경 : window(또는 self, this, frames)
- Node.js 환경 : global
💡 globalThis
브라우저, Node 환경 통일한 전역객체 식별자.
브라우저, Node 환경 통일한 전역객체 식별자.
- 전역 객체는 표준 빌트인 객체(Object, Stiring, …), 호스트 객체, var로 선언한 전역 변수, 전역함수를 프로퍼티로 가짐.
- 계층 구조상 어떤 객체에도 속하지 않은 모든 빌트인 객체(표준 빌트인 객체, 호스트 객체)의 최상위 객체.
- 전역 객체 자신은 어떤 객체의 프로퍼티도 아니며 계층적 구조상 표준 빌트인 객체와 호스트 객체를 프로퍼티로 소유한다는 의미.
- 개발자가 의도적으로 생성할 수 없음. === 전역 객체를 생성할 수 있는 생성자 함수가 제공x.
- 전역 객체의 프로퍼티를 참조할 때 window 생략 가능.
21-09
// 문자열 'F'를 16진수로 해석하여 10진수로 변환하여 반환한다.
window.parseInt('F', 16); // -> 15
// window.parseInt는 parseInt로 호출할 수 있다.
parseInt('F', 16); // -> 15
window.parseInt === parseInt; // -> true
- 전역객체는 Object, String, Number, … 같은 모든 표준 빌트인 객체를 프로퍼티로 가지고 있음.
- var 전역변수, 선언안하고 값을 할당한 암묵적 전역, 전역 함수는 전역 객체의 프로퍼티가 됨.
21-10
// 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로 선언한 전역변수는 전역 객체의 프로퍼티 아님.
전역 객체는 몇가지 프로퍼티와 메서드를 가지고 있음. window 생략하여 전역변수, 전역함수처럼 사용가능.
1) 빌트인 전역 프로퍼티
전역 객체의 프로퍼티.
a) Infinity
// 전역 프로퍼티는 window를 생략하고 참조할 수 있다.
console.log(window.Infinity === Infinity); // true
// 양의 무한대
console.log(3/0); // Infinity
// 음의 무한대
console.log(-3/0); // -Infinity
// Infinity는 숫자값이다.
console.log(typeof Infinity); // number
b) NaN
console.log(window.NaN); // NaN
console.log(Number('xyz')); // NaN
console.log(1 * 'string'); // NaN
console.log(typeof NaN); // number
c) undefined
console.log(window.undefined); // undefined
var foo;
console.log(foo); // undefined
console.log(typeof undefined); // undefined
2) 빌트인 전역 함수
전역객체의 메서드
a) eval
b) isFinite
// 인수가 유한수이면 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
c) isNaN
// 숫자
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
d) parseFloat
// 문자열을 실수로 해석하여 반환한다.
parseFloat('3.14'); // -> 3.14
parseFloat('10.00'); // -> 10
// 공백으로 구분된 문자열은 첫 번째 문자열만 변환한다.
parseFloat('34 45 66'); // -> 34
parseFloat('40 years'); // -> 40
// 첫 번째 문자열을 숫자로 변환할 수 없다면 NaN을 반환한다.
parseFloat('He was 40'); // -> NaN
// 앞뒤 공백은 무시된다.
parseFloat(' 60 '); // -> 60
e) parseInt
// 문자열을 정수로 해석하여 반환한다.
parseInt('10'); // -> 10
parseInt('10.123'); // -> 10
f) encodeURI / decodeURI
// 완전한 URI
const uri = 'http://example.com?name=이웅모&job=programmer&teacher';
// encodeURI 함수는 완전한 URI를 전달받아 이스케이프 처리를 위해 인코딩한다.
const enc = encodeURI(uri);
console.log(enc);
// http://example.com?name=%EC%9D%B4%EC%9B%85%EB%AA%A8&job=programmer&teacher
const uri = 'http://example.com?name=이웅모&job=programmer&teacher';
// encodeURI 함수는 완전한 URI를 전달받아 이스케이프 처리를 위해 인코딩한다.
const enc = encodeURI(uri);
console.log(enc);
// http://example.com?name=%EC%9D%B4%EC%9B%85%EB%AA%A8&job=programmer&teacher
// decodeURI 함수는 인코딩된 완전한 URI를 전달받아 이스케이프 처리 이전으로 디코딩한다.
const dec = decodeURI(enc);
console.log(dec);
// http://example.com?name=이웅모&job=programmer&teacher
g) encodeURIComponent / decodeURIComponent
// URI의 쿼리 스트링
const uriComp = 'name=이웅모&job=programmer&teacher';
// encodeURIComponent 함수는 인수로 전달받은 문자열을 URI의 구성요소인 쿼리 스트링의 일부로 간주한다.
// 따라서 쿼리 스트링 구분자로 사용되는 =, ?, &까지 인코딩한다.
let enc = encodeURIComponent(uriComp);
console.log(enc);
// name%3D%EC%9D%B4%EC%9B%85%EB%AA%A8%26job%3Dprogrammer%26teacher
let dec = decodeURIComponent(enc);
console.log(dec);
// 이웅모&job=programmer&teacher
// encodeURI 함수는 인수로 전달받은 문자열을 완전한 URI로 간주한다.
// 따라서 쿼리 스트링 구분자로 사용되는 =, ?, &를 인코딩하지 않는다.
enc = encodeURI(uriComp);
console.log(enc);
// name=%EC%9D%B4%EC%9B%85%EB%AA%A8&job=programmer&teacher
dec = decodeURI(enc);
console.log(dec);
// name=이웅모&job=programmer&teacher
3) 암묵적 전역
21-37
var x = 10; // 전역 변수
function foo () {
// 선언하지 않은 식별자에 값을 할당
y = 20; // window.y = 20;
}
foo();
// 선언하지 않은 식별자 y를 전역에서 참조할 수 있다.
console.log(x + y); // 30
선언하지 않은 식별자에 값을 할당하면 전역 객체의 프로퍼티가 된다. : 암묵적 전역
- 하지만 단지 전역 객체의 프로퍼티로 추가되었을 뿐이기 때문에 y는 변수가 아님.
- 그래서 변수 호이스팅 발생x
21-38
// 전역 변수 x는 호이스팅이 발생한다.
console.log(x); // undefined
// 전역 변수가 아니라 단지 전역 객체의 프로퍼티인 y는 호이스팅이 발생하지 않는다.
console.log(y); // ReferenceError: y is not defined
var x = 10; // 전역 변수
function foo () {
// 선언하지 않은 식별자에 값을 할당
y = 20; // window.y = 20;
}
foo();
// 선언하지 않은 식별자 y를 전역에서 참조할 수 있다.
console.log(x + y); // 30
- y는 delete 연산자로 삭제 가능. 전역 변수는 삭제 불가.
21-39
var x = 10; // 전역 변수
function foo () {
// 선언하지 않은 식별자에 값을 할당
y = 20; // window.y = 20;
console.log(x + y);
}
foo(); // 30
console.log(window.x); // 10
console.log(window.y); // 20
delete x; // 전역 변수는 삭제되지 않는다.
delete y; // 프로퍼티는 삭제된다.
console.log(window.x); // 10
console.log(window.y); // undefined
'JS' 카테고리의 다른 글
모던 자바스크립트 Deep Dive - 실행 컨텍스트 (0) | 2024.01.17 |
---|---|
모던 자바스크립트 Deep Dive - this (0) | 2024.01.16 |
모던 자바스크립트 Deep Dive - 생성자 함수에 의한 객체 생성 (2) | 2024.01.14 |
모던 자바스크립트 Deep Dive - let, const 키워드와 블록 레벨 스코프 (0) | 2024.01.13 |
모던 자바스크립트 Deep Dive - 전역 변수의 문제점 (0) | 2024.01.13 |
댓글