[스터디]모던 자바스크립트 딥다이브 21장 빌트인 객체
21.1 자바스크립트 객체의 분류
-
표준 빌트인 객체
- ECMAScript 사양에 정의된 객체를 말하며, 애플리케이션 전역의 공통기능을 제공한다.
- 자바스크립트 실행 환경(브라우저 또는 Node.js 환경)과 관계없이 언제나 사용할 수 있다.
- 표준 빌트인 객체는 전역 객체의 프로퍼티로서 제공된다. -> 따라서 별도의 선언 없이 전역 변수처럼 언제나 참조 가능하다.
-
호스트 객체
- ECMAScript 사양에 정의되어 있지 않지만 자바스크립트 실행 환경(브라우저 or Node .js)에서 추가로 제공하는 객체를 의미한다.
- 브라우저 환경에서는 DOM, BOM, Canvas, XMLHttpRequest, fetch등과 같은 클라이언트 사이드 Web API를 호스트 객체로 제공한다.
- Node.js 환경에서는 Node.js 고유의 API를 호스트 객체로 제공한다.
-
사용자 정의 객체
- 표준 빌트인 객체와 호스트 객체처럼 기본 제공되는 객체가 아닌 사용자가 직접 정의한 객체를 의미한다.
21.2 표준 빌트인 객체
- 자바스크립트는 Object, String, Number, Boolean, Symbol, Date등 40여 개의 표준 빌트인 객체를 제공한다.
-
Math, Reflect, JSON을 제외한 표준 빌트인 객체는 모두 인스턴스를 생성할 수 있는 생성자 함수 객체이다.
- 생성자 함수 객체인 표준 빌트인 객체는
프로토타입 메서드
와정적 메서드
를 제공한다.- 해당 객체가 생성한 인스턴스의 프로토타입은 표준 빌트인 객체의
prototype 프로퍼티
에 바인딩된 객체이다.
- 해당 객체가 생성한 인스턴스의 프로토타입은 표준 빌트인 객체의
-
생성자 함수 객체가 아닌 표준 빌트인 객체는
정적 메서드
만 제공한다.// 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
- 생성자 함수 객체인 표준 빌트인 객체는
21.3 원시값과 래퍼 객체
표준 빌트인 생성자 함수가 존재하는 이유는 무엇일까?
-
원시값은 객체가 아니므로 프로퍼티나 메서드를 가질 수 없는데도 원시값인 문자열이 마치 객체처럼 동작한다.
const str = "hello"; // 원시 타입인 문자열이 프로퍼티와 메서드를 갖고 있는 객체처럼 동작한다. console.log(str.length); //5 console.log(str.toUpperCase()); // HELLO
-
이는, 원시값인 문자열, 숫자, 불리언 값의 경우 이들 원시값에 대해 마치 객체처럼 마침표 표기법(또는 대괄호 표기법)으로 접근하면 자바스크립트 엔진이 일시적으로 원시값을 연관된 객체로 변환해주기 때문이다. -> 즉, 원시값을 객체처럼 사용하면 자바스크립트 엔진은 암묵적으로 연관된 객체를 생성하여 생성된 객체로 프로퍼티에 접근하거나 메서드를 호출하고 다시 원시값으로 되돌린다.
-
이처럼 문자열, 숫자, 불리언 값에 대해 객체처럼 접근하면 생성되는 임시 객체를
래퍼 객체
라 한다.
-
-
ex) 문자열에 대해 마침표 표기법으로 접근하면 발생하는 상황
-
접근하는 순간 래퍼 객체인 String 생성자 함수의
인스턴스
가 생성되고 문자열은 래퍼 객체의[[StringData]] 내부 슬롯
에 할당된다.const str = "hi"; //원시 타입인 문자열이 래퍼객체인 String 인스턴스로 변환된다. console.log(str.length); // 2 console.log(str.toUpperCase()); // HI // 래퍼 객체로 프로퍼티에 접근하거나 메서드를 호출한 후, 다시 원시값으로 되돌린다. console.log(typeof str); // string
-
이때 문자열 래퍼 객체인 String 생성자 함수의
인스턴스
는 String.prototype의 메서드를 상속받아 사용할 수 있다. -
그 후 래퍼 객체의 처리가 종료되면 래퍼 객체의
[[StringData]]
내부 슬롯에 할당된 원시값으로 원래의 상태, 즉 식별자가 원시값을 갖도록 되돌리고 래퍼 객체는 가비지 컬렉션(더이상 사용하지 않는 메모리를 발견하고 이를 해제해주는 역할)의 대상이 된다.
-
-
문자열과 같이 숫자와 불리언도 동일하게 작동한다.
21.4 전역 객체
-
전역 객체는 코드가 실행되기 이전 단계에 자바스크립트 엔진에 의해 어떤 객체보다도 먼저 생성되는 특수한 객체이며, 어떤 객체에도 속하지 않은 최상위 객체다.
-
브라우저 환경에서는 window, Node.js환경에서는 global이 전역 객체이다.
-
전역 객체는 표준 빌트인 객체와 환경에 따른 호스트 객체, 그리고 var 키워드로 선언한 전역 변수와 전역 함수를
프로퍼티
로 갖는다.-> 즉, 전역 객체는 계층적 구조상 어떤 객체에도 속하지 않은 모든 빌트인 객체(표준 빌트인 객체와 호스트 객체)의 최상위 객체다.
-
전역 객체가 최상위 객체라는 것은 프로토타입 상속 관계상에서 최상위 객체라는 의미가 아니다
-
전역 객체 자신은 어떤 객체의 프로퍼티도 아니며 객체의 계층적 구조상 표준 빌트인 객체와 호스트 객체를 프로퍼티로 소유한다는 것을 말한다.
-
전역 객체의 특징
-
전역 객체는 개발자가 의도적으로 생성할 수 없다. 즉, 전역 객체를 생성할 수 있는 생성자 함수가 제공되지 않는다.
-
전역 객체의 프로퍼티를 참조할 때 window(또는 global)를 생략할 수 있다.
-
전역 객체는 모든 표준 빌트인 객체를 프로퍼티로 가지고 있다.
-
자바스크립트 실행 환경에 따라 추가적인 프로퍼티와 메서드를 갖는다.
-
var 키워드로 선언한 전역 변수와 선언하지 않은 변수에 값을 할당한
암묵적 전역
, 그리고 전역 함수는 전역 객체의 프로퍼티가 된다. -
let이나 const 키워드로 선언한 전역 변수는 전역 객체의 프로퍼티가 아니다. 보이지 않는 개념적인 블록(전역 렉시컬 환경의 선언적 환경 레코드)내에 존재하기 때문이다.
-
브라우저 환경의 모든 자바스크립트 코드는 하나의 전역 객체 window를 공유한다. 여러 개의 script 태그를 통해 자바스크립트 코드를 분리해도 하나의 전역 객체
window
를 공유한다.
21.4.1 빌트인 전역 프로퍼티
- 빌트인 전역 프로퍼티는 전역 객체의 프로퍼티를 의미한다.
빌트인 전역 프로퍼티
- Inifinity
- 무한대를 나타내는 숫자값 Infinity를 갖는다.
- NaN
- 숫자가 아님을 나타내는 숫자값 NaN을 갖는다.
- undefined
- 원시 타입 undefined를 값으로 갖는다.
21.4.2 빌트인 전역 함수
- 애플리케이션 전역에서 호출할 수 있는 빌트인 함수로서 전역 객체의 메서드이다.
빌트인 전역 함수 종류
-
eval
- 자바스크립트 코드를 나타내는 문자열을 인수로 전달받는다.
- 전달받은 문자열 코드가 표현식이라면 eval 함수는 문자열 코드를 런타임에 평가하여 값을 생성한다.
- 전달받은 인수가 표현식이 아닌 문이라면 eval 함수는 문자열 코드를 런타임에 실행한다.
// 표현식인 문 eval("1 + 2;"); // 3 // 표현식이 아닌 문 eval("var x = 5;"); // undefined // eval 함수에 의해 런타임에 변수 선언문이 실행되어 x 변수가 선언되었다. console.log(x); // 5 // 객체 리터럴은 반드시 괄호로 둘러싼다. const o = oval("({ a: 1 })"); console.log(o); // {a: 1} // 함수 리터럴은 반드시 괄호로 둘러싼다. const f = eval("(function() { return 1;})"); console.log(f()); // 1
-
eval 함수는 자신이 호출된 위치에 해당하는 기존의 스코프를 런타임에 동적으로 수정한다.
-
함수가 호출되면 런타임 이전에 먼저 함수 몸체 내부의 모든 선언문을 먼저 실행하고 그 결과를 스코프에 등록한다.
-
하지만 해당 함수 내부에 eval 함수는 기존의 스코프를 런타임에 동적으로 수정한다.
✔️eval 함수의 사용을 금지해야하는 이유
-
eval 함수를 통해 사용자로부터 입력받은 콘텐츠를 실행하는 것은 보안에 매우 취약하기 때문에
-
eval 함수를 통해 실행되는 코드는 자바스크립트 엔진에 의해 최적화가 수행되지 않으므로 일반적인 코드 실행에 비해 처리 속도가 느리기 때문에
-
isFinite
- 전달받은 인수가 정상적인 유한수인지 검사하여 유한수이면 true를 반환하고, 무한수이면 false를 반환하다.
-
isNaN
- 전달받은 인수가 NaN인지 검사하여 그 결과를 불리언 타입으로 반환한다.
-
parseFloat
- 전달받은 문자열 인수를 부동 소수점 숫자, 즉 실수로 해석하여 반환한다.
-
parseInt
-
전달받은 문자열 인수를 정수로 해석하여 반환한다.
-
두 번째 인수로 진법을 나타내는 기수를 전달할 수 있다. 기수를 지정하면 첫 번째 인수로 전달된 문자열을 해당 기수의 숫자로 해석하여 반환한다. 이때 반환값은 언제나 10진수다.
// '10'을 10진수로 해석하고 그 결과를 10진수 정수로 반환한다. parseInt("10"); // 10 // '10'을 2진수로 해석하고 그 결과를 10진수 정수로 반환한다. parseInt("10"); // 2
-
-
encodeURI
-
완전한 URI를 문자열로 전달받아 이스케이프 처리를 위해 인코딩한다.
// 완전한 URI const uri = "http://naver.com?name=가나다&job=programmer&teacher"; // encodeURI 함수는 완전한 URI를 전달받아 이스케이프 처리를 위해 인코딩한다. const enc = encodeURI(uri); console.log(enc); // http://naver.com?name=%EG%23%D3%E3%FE%U5%O5%A8&job=programmer&teacher
-
-
decodeURI
-
인코딩된 URI를 인수로 전달받아 이스케이프 처리 이전으로 디코딩 한다.
// http://naver.com?name=%EG%23%D3%E3%FE%U5%O5%A8&job=programmer&teacher const enc = encodeURI(uri); const dec = decodeURI(enc); console.log(dec); // http://naver.com?name=가나다&job=programmer&teacher
-
-
encodeURIComponent
- URI 구성 요소를 인수로 전달받아 인코딩한다.
- 인수로 전달된 문자열을 URI의 구성요소인 쿼리 스트링의 일부로 간주한다. 따라서 쿼리 스트링 구분자로 사용되는 =, ?, &까지 인코딩한다.
21.4.3 암묵적 전역
var x = 10; // 전역 변수
function foo() {
// 선언하지 않은 식별자에 값을 할당
y = 20; // window.y = 20;
}
foo();
// 선언하지 않은 식별자 y를 전역에서 참조할 수 있다.
console.log(x + y); // 30
-
함수 foo 내부의 y처럼 선언하지 않은 식별자에 값을 할당하면 전역 객체의 프로퍼티가 된다.
-
foo 함수가 호출되면 자바스크립트 엔진은 y 변수에 값을 할당하기 위해 먼저
스코프 체인
을 통해 선언된 변수인지 확인한다. 이때 foo 함수의 스코프와 전역 스코프 어디에서도 y 변수의 선언을 찾을 수 없으므로참조 에러
가 발생한다. -> 하지만 자바스크립트 엔진은 y = 20을window.y = 20
으로 해석하여 전역 객체에 프로퍼티를 동적 생성한다. 이러한 현상을 암묵적 전역이라 한다.- y는 변수 선언 없이 단지 전역 객체의 프로퍼티로 추가되었을 뿐이다. ->따라서 변수가 아니기때문에 변수 호이스팅이 발생하지 않는다.
댓글남기기