5 분 소요

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는 변수 선언 없이 단지 전역 객체의 프로퍼티로 추가되었을 뿐이다. ->따라서 변수가 아니기때문에 변수 호이스팅이 발생하지 않는다.

댓글남기기