Study/모던 자바스크립트 Deep Dive

[모던 자바스크립트 Deep Dive] 16장 ~ 20장

chaeon1 2025. 3. 27. 22:27

16장 프로퍼티 어트리뷰트

16.1 내부 슬롯과 내부 메서드

  • ECMAScript 사양에서 사용하는 의사 프로퍼티와 의사 메서드
  • 직접 접근 불가 (일부만 간접 접근 가능)
  • 내부 슬롯: [[Prototype]]
    • __proto__: [[Prototype]] 내부 슬롯에 간접 접근하는 수단

16.2 프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체

  • 자바스크립트 엔진이 프로퍼티 생성 시 자동 정의
  • 프로퍼티 어트리뷰트 (직접 접근 불가)
    • [[Value]]
    • 값 변경 가능 여부 [[Writable]]
    • 열거 가능 여부 [[Enumerable]]
    • 재정의 가능 여부 [[Configurable]]
  • Object.getOwnPropertyDescriptor
    • 프로퍼티 어트리뷰트 간접 확인 가능
    • 모든 프로퍼티 정보 한 번에 조회 가능

16.3 데이터 프로퍼티와 접근자 프로퍼티

  • 데이터 프로퍼티 (일반적인 프로퍼티)

    • [[Value]]: 프로퍼티 키를 통해 프로퍼티 값에 접근하면 반환되는 값
    • [[Writable]]: 프로퍼티 값의 변경 가능 여부, 불리언
    • [[Enumerable]]: 프로퍼티의 열거 가능 여부, 불리언
    • [[Configurable]]: 프로퍼티의 재정의 가능 여부, 불리언
  • 접근자 프로퍼티 (getter/setter 함수)

    • [[Get]]: 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 읽을 때 호출되는 접근자 함수
    • [[Set]]: 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 저장할 때 호출되는 접근자 함수
    • [[Enumerable]]: [[Enumerable]]과 같음
    • [[Configurable]]: [[Configurable]]과 같음

16.4 프로퍼티 정의

  • Object.defineProperty 메서드를 사용해 프로퍼티 정의 가능
  • 프로퍼티 디스크립터 객체의 프로퍼티 일부 생략 가능
    • 생략 시 기본 값 undefined
      • value
      • get
      • set
    • 생략 시 기본 값 false
      • writable
      • enumerable
      • configurable

16.5 객체 변경 방지

구분 메서드 프로퍼티 추가 프로퍼티 삭제 프로퍼티 값 읽기 프로퍼티 값 쓰기 프로퍼티 어트리뷰트 재정의
객체 확장 금지 Object.preventExtensions X O O O O
객체 밀봉 Object.seal X X O O X
객체 동결 Object.freeze X X O X X

17장 생성자 함수에 의한 객체 생성

17.1 Object 생성자 함수

  • new Object()로 객체 생성 후 프로퍼티 추가
  • Object 생성자 함수를 사용하는 방식은 잘 쓰지 않음
  • 빌트인 생성자 함수
    • String
    • Number
    • Boolean
    • Function
    • Array
    • Date
    • RegExp

17.2 생성자 함수

  • 객체 리터럴 방식의 문제점

    • 동일한 구조의 객체를 여러 개 만들려면 비효율적

      const circle1 = { radius: 5, getDiameter() { return 2 * this.radius; } };
      const circle2 = { radius: 10, getDiameter() { return 2 * this.radius; } };
    • 생성자 함수 방식의 장점

      • 탬플릿(클래서)처럼 사용 가능

        function Circle(radius) {
          this.radius = radius;
          this.getDiameter = function () {
            return 2 * this.radius;
          };
        }
        
        const circle1 = new Circle(5);
        const circle2 = new Circle(10);
    • this

      호출 방식 this가 기리키는 값(this 바인딩)
      일반 함수로서 호출 전역 객체
      메서드로서 호출 메서드를 호출한 객체(마침표 앞의 객체)
      생성자 함수로서 호출 생성자 함수가 (미래에) 생성할 인스턴스
    • 생성자 함수의 인스턴스 생성 과정

      • 인스턴스 생성과 this 바인딩
      • 인스턴스 초기화
      • 인스턴스 반환
    • 내부 메서드 [[Call]][[Construct]]

      • [[Call]]: 일반 함수 호출
      • [[Construct]]: new와 함께 호출
    • constructornon-constructor의 구분

      • constructor: 함수 선언문, 함수 표현식, 클래스
      • non-constructor: 메서드, 화살표 함수
    • new 연산자

      • new 연산자와 함께 함수를 호출하면 해당 함수는 생성자 함수로 동작
      • 단, 함께 호출하는 함수는 constructor이어야 함
    • new.target

      • 생성자 함수가 new 연산자 없이 호출되는 것을 방지하기 위해 사용

18장 함수와 일급 객체

18.1 일급 객체

  • 일급 객체
    1. 무명의 리터럴로 생성 가능, 런타임에 생성 가능
    2. 변수나 자료구조(객체, 배열 등)에 저장 가능
    3. 함수의 매개변수에 전달 가능
    4. 함수의 반환값으로 사용 가능

18.2 함수 객체의 프로퍼티

  • console.dir() 메서드를 사용하여 함수 내부 구조 확인 가능
  • 고유 프로퍼티
  • arguments: 함수 호출 시 전달된 인수 정보를 담은 유사 배열 객체
  • caller: 함수를 호출한 직전의 함수 참조 (비표준, 사용 권장 X)
  • length: 함수 정의 시 선언한 매개변수의 개수를 가리킴
  • name: 함수의 이름을 나타냄
  • prototype: 모든 객체가 가진 [[Prototype]] 내부 슬롯에 접근하기 위한 접근자 프로퍼티

19장 프로토타입

19.1 객체지향 프로그래밍

  • 실체(사물, 개념)를 프로그램으로 모델링하는 패러다임
  • 전통적인 명령형 프로그래밍과 달리, 프로그램을 객체라는 독립적인 단위의 집합으로 구성
  • 객체(Object): 상태(state)와 동작(behavior)을 하나로 묶은 복합 자료구조
  • 속성/프로퍼티(Property): 객체의 상태를 나타내는 값
  • 메서드(Method): 객체의 동작을 나타내는 함수
  • 추상화(Abstraction): 복잡한 실체에서 필요한 부분만 간추려 객체로 표현하는 것
  • 문제점
    • 생성자 함수로 객체를 만들면 인스턴스마다 동일한 메서드가 중복 생성
    • 인스턴스를 여러 개 만들면 메서드도 각각 만들어져 메모리 낭비 발생

19.2 상속과 프로토타입

  • 객체가 다른 객체의 프로퍼티/메서드를 물려받아 사용하는 개념
  • 자바스크립트는 프로토타입 기반 상속을 제공하여 중복을 줄이고 코드 재사용을 용이하게 함
  • 장점
    • 메서드는 프로토타입에 하나만 정의하고, 모든 인스턴스가 공유
    • 메모리 절약, 성능 개선 가능

19.3 프로토타입 객체

  • 객체 간 상속을 구현하는 핵심 구조
  • 모든 객체는 [[Prototype]]이라는 내부 슬롯을 가지고 있고, 이것이 상위 객체를 참조함
  • 프로토타입 연결
    • 객체 -> 프로토타입 -> 생성자 함수가 서로 연결
    • __proto__ 프로퍼티를 통해 자신의 프로토타입에 접근 가능
  • proto 접근자 프로퍼티
    • 내부 슬롯 [[Prototype]]간접 접근하기 위한 접근자 프로퍼티
    • gettersetter 함수로 구성
  • 프로토타입 체인
    • 객체가 가진 프로퍼티를 찾지 못하면 __proto__가 가리키는 프로토타입에서 탐색을 계속함
    • 프로토타입 체인의 최상위는 Object.prototype

19.4 리터럴 표기법에 의해 생성된 객체의 생성자 함수와 프로토타입

리터럴 표기법 생성자 함수 프로토타입
객체 리터럴 Object Object.prototype
함수 리터럴 Function Function.prototype
배열 리터럴 Array Array.prototype
정규 표현식 리터럴 RegExp RegExp.prototype

19.5 프로토타입의 생성 시점

  • 프로토타입은 생성자 함수가 생성되는 시점에 함께 생성
  • Object, Array, Function 등의 빌트인 생성자 함수도 함수 정의 시점에 프로토타입이 함께 생성

19.6 객체 생성 방식과 프로토타입

  • 객체 생성 방식
    • 객체 리터럴
    • Object 생성자 함수
    • 사용자 정의 생성자 함수
    • Object.create 메서드
    • 클래스 (ES6)
  • 객체 리터럴에 의해 생성된 객체의 프로토타입: Object.prototype
  • Object() 생성자 함수에 의해 생성된 객체의 프로토타입: Object.prototype
  • 생성자 함수로 객체를 만들면, 해당 객체의 프로토타입은 생성자 함수의 prototype 프로퍼티에 바인딩된 객체

19.7 프로토타입 체인

  • 객체에서 프로퍼티나 메서드가 없으면 [[Prototype]]을 따라 부모 객체로 검색을 이어가는 방식

    function Person(name) {
      this.name = name;
    }
    
    Person.prototype.sayHello = function () {
      console.log(`Hi! My name is ${this.name}`);
    };
    
    const me = new Person('Lee');
    
    console.log(me.hasOwnProperty('name')); // true
    console.log(Object.getPrototypeOf(me) === Person.prototype); // true
    console.log(Object.getPrototypeOf(Person.prototype) === Object.prototype); // true
    • 프로토타입 체인 흐름: mePerson.prototypeObject.prototypenull
  • 프로토타입 체인

    • 객체 간 상속 관계에서 프로퍼티 검색
    • 객체지향 상속 메커니즘 구현
  • 스코프 체인

    • 함수의 중첩 관계에서 식별자 검색
    • 렉시컬 환경, 클로저 구현

19.8 오버라이딩과 프로퍼티 섀도잉

  • 프로퍼티 섀도잉: 상속 관계에 의해 프로퍼티가 가려지는 현상
  • 오버라이딩: 상위 클래스가 가지고 있는 메서드를 하위 클래스가 재정의하여 사용하는 방식

19.9 프로토타입의 교체

  • 생성자 함수에 의한 프로토타입 교체
    • 생성자 함수의 prototype 프로퍼티를 새로운 객체 리터럴로 교체 가능
    • constructor 프로퍼티와 생성자 함수 간의 연결이 끊어짐 -> 새 프로토타입 객체에 constructor를 명시적으로 추가
  • 인스턴스에 의한 프로토타입 교체
    • 인스턴스의 __proto__ 접근자 프로퍼티 또는 Object.setPrototypeOf 메서드를 사용하여 프로토타입 변경 가능
    • 이미 생성된 인스턴스의 프로토타입을 동적으로 변경

19.10 instanceof 연산자

  • 객체가 특정 생성자 함수의 인스턴스인지 확인하는 연산자
  • 우변의 생성자 함수의prototype이 좌변 객체의 프로토타입 체인 상에 존재하면 true
  • 프로토타입을 교체하면 instanceof 결과가 달라질 수 있음 -> 새로운 프로토타입 객체를 생성자 함수의 prototype 프로퍼티에 할당

19.11 직접 상속

  • Object.create에 의한 직접 상속
    • Object.create을 사용하면 명시적으로 프로토타입을 설정하여 객체 생성 가능
    • new 없이도 객체 생성 가능하며, 객체 리터럴도 상속 가능

19.12 정적 프로퍼티/메서드

  • 정적 프로퍼티/메서드는 생성자 함수로 인스턴스를 생성하지 않고도 참조/호출할 수 있는 프로퍼티와 메서드를 의미
  • 정적 프로퍼티/메서드는 생성자 함수에 직접 추가되며, 인스턴스로 접근할 수 없음
  • Object.create(): Object 생성자 함수의 정적 메서드
  • Object.prototype.hasOwnProperty(): 모든 객체가 호출할 수 있는 프로토타입 메서드

19.13 프로퍼티 존재 확인

  • in 연산자
    • 객체 내 특정 프로퍼티 존재 여부 확인 가능
    • 프로토타입 체인에 있는 프로퍼티도 검색됨
    • Reflect.has() 메서드를 사용하면 동일한 기능 수행
  • Object.prototype.hasOwnProperty() 메서드
    • 객체 자신의 프로퍼티 여부만 확인
    • 상속받은 프로퍼티는 확인하지 않음

19.14 프로퍼티 열거

  • for...in
    • 객체의 모든 열거 가능한 프로퍼티를 순회하며, 프로토타입 체인에 있는 프로퍼티까지 포함
    • 단, Object.prototype의 기본 프로퍼티는 열거되지 않음
    • 객체 자신의 프로퍼티만 열거하려면 hasOwnProperty()를 활용
  • Object.keys/values/entries 메서드
    • Object.keys(obj): 객체의 프로퍼티 키 배열 반환
    • Object.values(obj): 객체의 프로퍼티 값 배열 반환
    • Object.entries(obj): 키-값 쌍을 배열 형태로 반환

20장 strict mode

20.1 strict mode란?

  • 자바스크립트 문법을 엄격히 적용하는 기능
    • 잠재적인 오류를 방지
    • 안정적인 코드 작성
  • 암묵적 전역 방지
    • 선언되지 않은 변수를 사용하면 자동으로 전역 변수가 되지만, Strict Mode에서는 ReferenceError 발생
  • ESLint 같은 린트 도구를 사용하면 비슷한 효과를 얻을 수 있음

20.2 strict mode의 적용

  • 'use strict';를 코드의 선두에 추가하여 적용 가능
  • 전역 적용: 모든 코드에 적용되지만, 외부 라이브러리와 충돌 가능성이 있어 추천 X
  • 함수 단위 적용: 특정 함수에서만 Strict Mode 적용 가능, 모든 함수에 적용하는 것은 번거롭기 때문에 권장되지 않음
  • 즉시 실행 함수(IIFE)로 적용: 전역 스코프를 오염시키지 않고 안전하게 적용 가능

20.5 strict mode가 발생시키는 에러

  • 암묵적 전역: 선언되지 않은 변수를 사용하면 ReferenceError 발생
  • 변수, 함수, 매개변수의 삭제: delete 연산자로 변수, 함수, 매개변수를 삭제하면 SyntaxError 발생
  • 매개변수 이름의 중복: 중복된 매개변수명을 사용하면 SyntaxError 발생
  • with 문의 사용: 스코프 체인 추가로 인해 성능이 저하될 수 있어 금지

20.6 strict mode를 적용에 의한 변화

  • 일반 함수의 this: 일반 함수에서 this를 사용할 필요가 없기 때문에 자동으로 undefined로 설정
  • arguments 객체: 매개변수 값을 변경해도 arguments 객체에는 반영되지 않음