writed by hanryu1109

1. 자바스크립트 객체의 분류

  1. 표준 빌트인 객체 (Native objects or Built-in objects or Global Objects)
  • ECMAScript 사양에 정의된 객체
  • 애플리케이션 전역의 공통 기능을 제공
  • 자바스크립트 실행 환경(브라우저 또는 Node.js 환경과 관계없이 언제나 사용)
  • 전역 객체의 프로퍼티로서 제공 => 별도의 선언 없이 전액 변수처럼 언제나 참조
  1. 호스트 객체
  • ECMAScript 사양에 정의되어 있지는 않음

  • 자바스크립트 실행 환경(브라우저 또는 Node.js 환경)에서 추가로 제공하는 객체

  • 브라우저 환경: DOM, BOM, Canvas, XMLHttpRequest, fetch, requestAnimationFrame, SVG, Web Storage, Web Component, Web Worker와 같은 클라이언트 사이트 Web API를 호스트 객체로 제공

  • Node.js 환경에서는 Node.js 고유의 API를 호스트 객체로 제공

    // Node.js 호스트 객체 예시
    // 파일 시스템 모듈 불러오기
    const fs = require("fs");
    
    // 파일 읽기
    fs.readFile("myFile.txt", "utf8", function (err, data) {
      if (err) throw err;
      console.log(data);
    });
    
    // 디렉토리 생성하기
    fs.mkdir("myDirectory", function (err) {
      if (err) throw err;
      console.log("디렉토리가 생성되었습니다.");
    });
  1. 사용자 정의 객체
  • 빌트인 객체와 호스트 객체처럼 기본으로 제공되는 객체가 아닌 사용자가 직접 정의한 객체

2. 표준 빌트인 객체

  1. 대부분의 빌트인 객체는 모두 인스턴스를 성생할 수 있는 생성자 함수 객체다 (ex. Object, String, Number, Boolean, Array ...)
  • 생섬자 함수 객체인 빌트인 객체는 프로토타입 메서드와 정적 메서드를 제공

  • 생성자 함수인 빌트인 객체가 생성한 인스턴스의 프로토타입은 / 빌트인 객체의 prototype 프로퍼티에 바인딩된 객체다.

  • 빌트인 객체의 prototype 프로퍼티에 바인딩 된 객체(예를 들어, Array.prototype)는 다양한 기능의 빌트인 프로토타입 메서드를 제공한다.

    // Array 생성자 함수에 의한 Array 객체 생성
    const arr = new Array(1, 2, 3);
    
    console.log(typeof arr); // object
    console.log(Object.getPrototypeOf(arr) === Array.prototype); // true
    arr.map((num) => console.log(num));
  • 빌트인 객체는 또한 인스턴스 없이도 호출 가능한 빌트인 정적 메서드를 제공한다.

    // Number 생성자 함수에 의한 Number 객체 생성
    const numObj = new Number(1.5); // Number {1.5}
    
    // toFixed는 Number.prototype 의 프로토타입 메서드다.
    // 이 프로토타입 메서드는 모든 Number 인스턴스가 상속을 통해 사용할 수 있다.
    // Number.prototype.toFixed 는 소수점 자리를 반올림 하여 문자열로 반환한다.
    console.log(numObj.toFixed()); // 2
    
    // IsInteger는 Number의 정적 메서드다.
    // IsInteger는 인스턴스 없이도 호출 가능하다.
    // Number.IsInteger 는 인수가 정수(integer)인지 검사하여 그 결과를 Boolean으로 반환한다.
    console.log(Number.isInteger(0.5)); // false
  1. 생성자 함수가 아닌 객체인 빌트인 객체 (ex. Math, Reflect, JSON ...)
  • 정적 메서드만 제공
    스크린샷 2023-09-20 오후 5 50 53
    스크린샷 2023-09-20 오후 5 48 09

3. 원시값과 래퍼 객체

  • 궁금증? : 문자열이나 숫자, 불리언 등의 원시값이 있는데도 문자열, 숫자, 불리언 객체를 생성하는 String, Number, Boolean 등의 표준 빌트인 생성자 함수가 존재하는 이유는 무엇일까?

  • 궁금증2? : 원시값은 객체가 아니므로 프로퍼티나 메서드를 가질 수 없는 데도 원시값인 문자열이 마치 객체처럼 동작하는데 어떻게 가능한 것일까?

    const str = "hello";
    
    // 원시 타입인 문자열이 프로퍼티와 메서드를 갖고 있는 객체처럼 동작한다.
    console.log(str.length); // 5
    console.log(str.toUpperCase()); // HELLO
  • 궁금증2 답변:

    • 원시값인 문자열, 숫자, 불리언의 값의 경우 이들 원시값에 대해 마치 객체처럼 마침표 표기법(또는 대괄호 표기법)으로 접근하면 자바스크립트 엔진이 일시적으로 원시값을 연관된 객체로 변환해 주기 때문이다.-
    • 즉, 원시값을 객체처럼 사용하면 1. 자바스크립트 엔진은 암묵적으로 연관된 객체를 생성하여 2. 생성된 객체로 프로퍼티에 접근하거나 메서드를 호출하고 3. 다시 원시값으로 되돌린다.
    • 🔥 문자열, 숫자, 불리언 값에 대해 객체처럼 접근하면 생성되는 임시 객체를 래퍼 객체(wrapper object)라 한다. 🔥
    • 문자열에 대해 마침표 표기법으로 접근하면 그 순간 래퍼 객체인 String 생성자 함수 / 의 인스턴스가 생성되고 / 문자열은 래퍼 객체의 [[StringData]] 내부 슬롯에 할당된다.
    const str = "hi";
    
    // 원시 타입인 문자열이 래퍼 객체인 String 인스턴스로 변환된다.
    // 문자열 래퍼 객체인 String 생성자 함수의 인스턴스(이 코드에서는 'str')는 String.prototype 의 메서드를 상속받아 사용할 수 있다.
    console.log(str.length); // 5
    console.log(str.toUpperCase()); // HI
    
    // 래퍼 객체로 프로퍼티에 접근하거나 메서드를 호출한 후, 다시 원시값으로 되돌린다.
    console.log(typeof str); // string
    • 그 후, 래퍼 객체의 처리가 종료되면 래퍼 객체의 [[StringData]] 내부 슬롯에 할당된 원시값으로 원래의 상태, 즉 식별자가 원시값을 갖도록 되돌리고 -> 래퍼 객체는 가비지 컬렉션의 대상이 된다.

    • 예제를 들어 다시 정리해보면!!

    // 1. 식별자 str은 문자열을 값으로 가지고 있다.
    const str = "hello";
    
    // 2. 식별자 str은 암묵적으로 생성된 래퍼 객체를 가리킨다.
    // 식별자 str의 값 "hello"는 래퍼 객체의 [[StringData]] 내부 슬롯에 할당된다.
    // 래퍼 객체에 name 프로퍼티가 동적 추가된다.
    str.name = "Lee";
    
    // 3. 식별자 str은 다시 원래의 문자열, 즉 래퍼 객체의 [[StringData]] 내부 슬롯에 할당된 원시값을 갖는다.
    // 이 때, 2에서 생성된 래퍼 객체는 아무도 참조하지 않는 상태이므로 가비지 컬렉션의 대상이 된다.
    
    // 4. 식별자 str은 새롭게 암묵적으로 생성된(2에서 생성된 래퍼 객체와는 다른) 래퍼 객체를 가리킨다.
    // 새롭게 생성된 래퍼 객체에는 name 프로퍼티가 존재하지 않는다.
    console.log(str.name); // undefined
    
    // 5. 식별자 str은 다시 원래의 문자열, 즉 래퍼 객체의 [[StringData]] 내부 슬롯에 할당된 원시값을 갖는다.
    // 이 때 4에서 생성된 래퍼 객체는 아무도 참조하지 않는 상태이므로 가비지 컬렉션의 대상이 된다.
    console.log(typeof str, str); // string hello
    • 결론적으로:
      • 문자열, 숫자, 불리언, 심벌은 암묵적으로 생성되는 래퍼 객체에 의해 마치 객체처럼 사용할 수 있으며, 표준 빌트인 객체인 String, Number, Boolean, Symbol의 프로토타입 메서드 또는 프로퍼티를 참조할 수 있다.
      • 따라서, String, Number, Boolean 생성자 함수를 new 연산자와 함께 호출하여 문자열, 숫자, 불리언 인스턴스를 생성할 필요가 없으며 권장하지도 않는다.
      • 문자열, 숫자, 불리언, 심벌 이외의 원시값인 nullundefined 는 래퍼 객체를 사용하지 않는다. 따라서 nullundefined 값을 객체처럼 사용하면 에러가 발생한다.

4. 전역 객체

  1. 전역 객체란?
  • 전역 객체는 코드가 실행되기 이전 단계에 자바스크립트 엔진에 의해 어떤 객체보다도 먼저 생성되는 특수한 객체이며, 어떤 객체에도 속하지 않은 최상위 객체다.
  1. 전역 객체 이름
  • 자바스크립트 환경에 따라 전역 객체를 지칭하는 이름이 제각각이다.
    • 브라우저 환경) 전역 객체 = window || self || this || frames 가 전역 객체를 가리킴
    • Node.js 환경) 전역 객체 = global
    • ES11에서 도입된 globalThis는 브라우저 환경과 Node.js 환경에서 전역 객체를 가리키던 다양한 식별자를 통일한 식별자다.
  1. 전역 객체의 프로퍼티
  • 표준 빌트인 객체(Object, Number, String, Boolean...)
  • 환경에 따른 호스트 객체(클라이언트 Web API 또는 Node.js의 호스트 API)
  • var 키워드로 선언한 전역 변수와 전역 함수
  1. 전역 객체 특징
  • 전역 객체는 개발자가 의도적으로 생성할 수 없다. 즉, 전역 객체를 생성할 수 있는 생성자 함수가 제공되지 않는다.
  • 전역 객체의 프로퍼티를 참조할 때 window(또는 global)를 생략할 수 있다.
  1. 주의점
  • let, const 키워드로 선언한 전역 변수는 전역 객체의 프로퍼티가 아니다.

  • let, const 키워드로 선언한 전역 변수는 보이지 않는 개념적인 블록(전역 렉시컬 환경의 선언적 환경 레코드)내에 존재하게 된다.

    let foo = 123;
    console.log(window.foo); // undefined
    
    var bar = 123;
    console.log(window.bar); // 123

4.1 빌트인 전역 프로퍼티

  • 빌트인 전역 프로퍼티는 = 전역 객체의 프로퍼티를 의미한다. 주로 애플리케이션 전역에서 사용하는 값을 제공한다.
  1. Infinity: Infinity 프로퍼티는 무한대를 나타내는 숫자값 Infinity 를 갖는다.
  2. NaN: 숫자가 아님(Not-a-Number)을 나타내는 숫자값 NaN을 갖는다. Number.NaN 프로퍼티와 같다.
  3. undefined: 원시 타입 undefined를 값으로 갖는다.

4.2 빌트인 전역 함수

  • 빌트인 전역 함수는 애플리케이션 전역에서 호출할 수 있는 빌트인 함수로서 전역 객체의 메서드다.
  1. eval (제가 생각했을 때는 그렇게 중요하지 않은 파트라.. 코드 없이 설명만 하겠습니다.)
  • 자바스크립트 코드를 나타내는 문자열을 인수로 전달받는다.
  • 전달받은 문자열 코드가 표현식이라면 eval 함수는 문자열 코드를 런타임에 평가하여 값을 생성한다.
  • 전달받은 문자열 코드가 표현식이 아닌 문이라면 eval 함수는 문자열 코드를 런타임에 실행한다.

  • eval 함수를 통해 사용자로부터 입력받은 콘텐츠를 실행하는 것은 보안에 매우 취약하다.
  • eval 함수를 통해 실행되는 코드는 자바스크립트 엔진에 의해 최적화가 수행되지 않으므로 일반적인 코드 시랭에 비해 처래 속도가 느리다.
  • 따라서 eval 함수 사용은 금지해야 한다.
  1. isFinite
  • 전달받은 인수가 정상적인 유한수인지 검사하여 유한수 이면 true 반환, 무한수이면 false를 반환

  • 전달받은 인수의 타입이 숫자가 아닌 경우, 숫자로 타입을 변환한 후 검사를 수행, 인수가 NaN으로 평가되면 false 반환

    isFinite(0); // true
    isFinite(2e64); // true
    isFinite("10"); // true
    isFinite(null); // true: null -> 0
    
    isFinite(Infinity); // false
    isFinite(-Infinity); // false
    
    isFinite(NaN); // false
    isFinite("Hello"); // false
    isFinite("2000/10/01"); // false
  1. isNaN
  • 전달받은 인수가 NaN인지 검사하여 그 결과를 불리언 타입으로 반환한다.

  • 전달받은 인수의 타입이 숫자가 아닌 경우 숫자로 타입을 변환한 후 검사를 수행한다.

    // 숫자
    isNaN(NaN); // ?
    isNaN(10); // ?
    
    // 문자열
    isNaN("blah"); // ?
    isNaN("10"); // ?
    isNaN("10.12"); // ?
    isNaN(""); // ?
    isNaN(" "); // ?
    
    // 불리언
    isNaN(true); // ?
    isNaN(null); // ?
    
    // undefined
    isNaN(undefined); // ?
    
    // 객체
    isNaN({}); // ?
    
    // date
    isNaN(new Date()); // ?
    isNaN(new Date().toString()); // ?
  1. parseFloat
  • 전달받은 문자열 인수를 부동 소숫점 숫자, 즉 실수로 해석하여 반환한다.

    // 문자열을 실수로 해석하여 반환한다.
    parseFloat("3.14"); // 3.14
    parseFloat("10.00"); // 10
    
    // 공백으로 구분된 문자열은 첫 번째 문자열만 변환한다.
    parseFloat("34 45 66"); // 34
    parseFloat("40 years"); // 40
    
    // 첫 번째 문자열을 숫자로 변환할 수 없다면 NaN을 반환한다.
    parseFloat("He was 40 years"); // NaN
    
    // 앞뒤 공백은 무시된다.
    parseFloat(" 60 "); // 60
  1. parseInt
  • 전달받은 문자열 인수를 정수로 해석하여 반환한다.
  • 전달받은 인수가 문자열이 아니면 문자열로 변환한 다음, 정수로 해석하여 반환한다.
  • 두 번째 인수로 진법을 나타내는 기수(2 ~ 36)를 전달할 수 있다. 기수를 지정하면 첫 번째 인수로 전달된 문자열을 해당 기수의 숫자로 해석하여 반환한다. 이때 반환값은 10진수다.
  1. encodeURI / decodeURI
  • 들어가기에 먼저! URI란? : URI는 인터넷에 있는 자원을 나타내는 유일한 주소를 말한다. URI의 하위 개념으로 URL, URN이 있다.
    Screenshot_20230921_162736_24 eBook

  • 들어가기에 먼저! 인코딩이란? : 인코딩이란 URI의 문자들을 이스케이프 처리하는 것을 말한다.

  • 이스케이프 처리란? : 이스케이프 처리는 네트워크를 통해 정보를 공유할 때 어떤 시스템에서도 읽을 수 있는 아스키 문제 셋(ASCII)으로 변환하는 것이다.

  • 예를 들어: 한글 가를 인코딩 하면 %EC%9E%90 게 변한다.

  • 단, 알파벳, 0~9의 숫자, - _ . ! ~ * ' ( ) 문자는 이스케이프 처리에서 제외된다.

  • 그러면 왜 이런게 필요한가? 왜 인코딩을 해야 하나? :(표준에 따르면) URL은 아스키 문자 셋으로만 구성되어야만 하며 한글 포함 아스키 문자 셋에 포함되지 않은 특수문자의 경우 URL에 포함될 수 없다.

  • 따라서 이스케이프 처리를 해줘야 특정 문자가 야기할 수 있는 문제를 예방할 수 있다.

  • encodeURI 함수는 완전한 URI를 문자열로 전달받아 이스케이프 처리를 위해 인코딩한다.

  • decodeURI 함수는 인코딩된 URI를 인수로 전달받아 이스케이프 처리 이전으로 디코딩한다.

    const uri = "http://example.com?name=이웅모&job=programmer";
    
    // `encodeURI` 함수는 완전한 URI를 문자열로 전달받아 이스케이프 처리를 위해 인코딩한다
    const enc = encodeURI(uri);
    console.log(enc); // http://example.com?name=%EC%9D%B4%EC%9B%85%EB%AA%A8&job=programmer
    
    // `decodeURI` 함수는 인코딩된 URI를 인수로 전달받아 이스케이프 처리 이전으로 디코딩한다.
    const dec = decodeURI(enc);
    console.log(dec); // http://example.com?name=이웅모&job=programmer
  1. encodeURIComponent / decodeURIComponent
  • encodeURIComponent 함수는 URI 구성요소를 인수로 전달받아 인코딩한다.

    • encodeURIComponent 함수는 인수로 전달된 문자열을 URI의 구성요소인 쿼리스트링의 일부로 간주한다. 따라서 쿼리 스트링 구분자로 사용되는 =, ?, &까지 인코딩한다.
    • 반면, encodeURI 함수는 매개변수로 전달된 문자열을 완전한 URI 전체라고 간주한다. 따라서 쿼리 스트링 구분자로 사용되는 =, ?, &은 인코딩하지 않는다.
  • decodeURIComponent 함수는 매개변수로 전달된 URI 구성 요소를 디코딩한다.

    // URI의 쿼리 스트링
    const uriComp = "name=이웅모&job=programmer";
    
    let enc = encodeURIComponent(uriComp);
    console.log(enc); // name%3D%EC%9D%B4%EC%9B%85%EB%AA%A8&job%3Dprogrammer
    
    let dec = decodeURIComponent(enc);
    console.log(dec); // name=이웅모&job=programmer
    
    enc = encodeURI(uriComp);
    console.log(enc); // name=%EC%9D%B4%EC%9B%85%EB%AA%A8&job=programmer
    
    dec = decodeURIComponent(enc);
    console.log(dec); // name=이웅모&job=programmer

4.3 암묵적 전역

var x = 10; // 전역 변수

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

// 선언하지 않은 식별자 y를 전역에서 참조할 수 있다.
console.log(x + y); // 30
  • 선언하지 않은 식별자에 값을 할당하면 전역 객체의 프로퍼티가 된다.
  • 위 예제 코드에서 y는 전역 객체의 프로퍼티가 되어 마치 전역 변수처럼 동작한다.
  • 이러한 현상을 암묵적 전역이라 한다.

  • 주의! y는 변수 선언 없이 단지 전역 객체의 프로퍼티로 추가되었을 뿐이다. 따라서 y는 변수가 아니다.
  • 따라서 y는 변수가 아니므로 변수 호이스팅이 발생하지 않는다.
// 전역 변수 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 연산자로 삭제할 수 있다.
  • 전역 변수는 프로퍼티이지만 delete 연산자로 삭제할 수 없다.
var x = 10; // 전역 변수

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

foo();

console.log(window.x); // 10
console.log(window.y); // 20

delete x; // 전역 변수는 삭제되지 않는다.
delete y; // 프로퍼티는 삭제된다.

console.log(window.x); // 10
console.log(window.y); // undefined
profile
Whether you're doing well or not, just keep going👨🏻‍💻🔥

0개의 댓글