[자바스크립트]

[JavaScript/DeepDive]19.프로토타입(3)

ki7348 2021. 5. 24. 20:54
  • [19.9] 프로토타입의 교체
  • 프로토타입은 임의의 다른 객체로 변경할 수 있다.
    • 부모 객체인 프로토타입을 동적으로 변경할 수 있다는 것을 의미한다.
      • 이러한 특징을 활용하여 객체 간의 상속 관계를 동적으로 변경할 수 있다.
        • 프로토타입은 생성자 함수 또는 인스턴스에 의해 교체할 수 있다.
  • 생성자 함수에 의한 프로토타입의 교체
  • 프로토타입을 교체하면 constructor 프로퍼티와 생성자 함수 간의 연결이 파괴된다.
    • 프로토타입으로 교체한 객체 리터럴에 constructor 프로퍼티를 추가하여 프로토타입의 constructor 프로퍼티를 되살린다.
  • 인스턴스에 의한 프로토타입의 교체
  • 프로토타입은 생성자 함수의 prototype 프로퍼티뿐만 아니라 인스턴스의 __proto__ 접근자 프로퍼티(또는 Object.getPrototypeOf 메서드)를 통해 접근할 수 있다.
    • 따라서 인스턴스의 __proto__ 접근자 프로퍼티(또는 Object.setPrototypeOf 메서드)를 통해 프로퍼티를 교체할 수 있다.
  • __proto__ 접근자 프로퍼티를 통해 프로토타입을 교체하는 것은 이미 생성된 객체의 프로토타입을 교체하는 것이다.

 

 

 

  • [19.10] instanceof 연산자
  • instanceof 연산자는 이항 연산자로서 좌변에 객체를 가리키는 식별자, 우변에 생성자 함수를 가리키는 식별자를 피연산자로 받는다.
    • 만약 우변의 피연산자가 함수가 아닌 경우 TypeError가 발생한다.
      • 객체 instanceof 생성자 함수
    • 우변의 생성자 함수의 prototype에 바인딩된 객체가 좌변의 객체의 프로토타입 체인 사엥 존재하면 true로 평가되고 그렇지 않는 경우에는 false로 평가된다.
      • // 생성자 함수
        function Person(name) {
             this.name = name;
        }
        const me = new Person('Lee');

        // Person.prototype이 me 객체의 프로토타입 체인 상에 존재하므로 true로 평가된다.
        console.log(me instanceof Person); // true

        // Object.prototype이 me 객체의 프로토타입 체인 상에 존재하므로 true로 평가된다.
        console.log(me instanceof Object); // true
  • instanceof 연산자는 프로토타입의 constructor 프로퍼티가 가리키는 생성자 함수를 찾는 것이 아니라 생성자 함수의 prototype에 바인딩된 객체가 프로토타입 체인 상에 존재하는지 확인한다.
    • 따라서 생성자 함수에 의해 프로토타입이 교체되어 constructor 프로퍼티와 생성자 함수 간의 연결이 파괴되어도 생성자 함수의 prototype 프로퍼티와 프로토타입 간의 연결은 파괴되지 않으므로 instanceof는 아무런 영향을 받지 않는다.

 

 

 

  • [19.11] 직접 상속
  • Object.create 메서드는 명시적으로 프로토타입을 지정하여 새로운 객체를 생성한다.
    • Object.create 메서드도 다른 객체 생성 방식과 마찬가지로 추상 연산 OrdinaryObjectCreate를 호출한다.
  • Object.create 메서드의 첫 번째매 개변수에는 생성할 객체의 프로토타입으로 지정할 객체를 전달한다.
  • 두 번째 매개변수에는 생성할 객체의 프로퍼티 키와 프로퍼티 디스크립터 객체로 이뤄진 객체를 전달한다.
    • 이 객체의 형식은 Object.defineProperties 메서드의 두 번째 인수와 동일한다.
      • 두 번째 인수는 옵션이므로 생략 가능하다.
  • Object.create 메서드의 장점은 다음과 같다.
    • new 연산자가 없어도 객체를 생성할 수 있다.
    • 프로토타입을 지정하면서 객체를 생성할 수 있다.
    • 객체 리터럴에 의해 생성된 객체도 상속받을 수 있다.

 

 

 

  • [19.12] 정적 프로퍼티/메서드
  • 정적 프로퍼티/메서드는 생성자 함수로 인스턴스를 생성하지 않아도 참조/호출할 수 있는 프로퍼티/메서드를 말한다.
    • // 생성자 함수
      function Person(name) {
           this.name = name;
      }

      // 프로토타입 메서드
      Person.prototype.sayHello = function ( ) {
           console.log(`Hi! My name is ${this.name}`);
      };

      // 정적 프로퍼티
      Person.staticProp = 'static prop';

      // 정적 메서드
      Person.staticMethod = function ( ) {
           console.log('staticMethod');
      };

      const me = new Person('Lee');

      // 생성자 함수에 추가한 정적 프로퍼티/메서드는 생성자 함수로 참조/호출한다.
      Person.staticMethod( ); // staticMethod

      // 정적 프로퍼티/메서드는 생성자 함수가 생성한 인스턴스로 참조/호출할 수 없다.
      // 인스턴스로 참조/호출할 수 있는 프로퍼티/메서드는 프로토타입 체인 상에 존재해야 한다.
      me.staticMethod( ); // TypeError: me.staticMethod is not a function
  • Perosn 생성자 함수는 객체이므로 자신의 프로퍼티/메서드를 소유할 수 있다.
  • Person 생성자 함수 객체가 소유한 프로퍼티/메서드를 정적 프로퍼티/메서드라 한다.
  • 정적 프로퍼티/메서드는 생성자 함수가 생성한 인스턴스로 참조/호출할 수 없다.
  • 생성자 함수가 생성한 인스턴스는 자신의 프로토타입 체인에 속한 객체의 프로퍼티/메서드에 접근할 수 있다.
    • 하지만 정적 프로퍼티/메서드는 인스턴스의 프로토타입 체인에 속한 객체의 프로퍼티/메서드가 아니므로 인스턴스로 접근할 수 없다.
  • 프로토타입 메서드를 호출하려면 인스턴스를 생성해야 하지만 정적 메서든느 인스턴스를 생성하지 않아도 호출할 수 있다.

 

 

 

  • [19.13] 프로퍼티 존재 확인
  • in 연산자
  • in 연산자는 객체 내에 특정 프로퍼티가 존재하는지 여부를 확인한다.
    • /**
       * key: 프로퍼티 키를 나타내는 문자열
       * object: 객체로 평가되는 표현식
      */
      key in project
  • in 연산자는 확인 대상 객체의 프로퍼티뿐만 아니라 확인 대상 객체가 상속받은 모든 프로토타입의 프로퍼티를 확인하므로 주의가 필요하다.
  • Object.prototype.hasOwnProperty 메서드
  • Object.prototpe.hasOwnProperty 메서드는 이름에서 알 수 있듯이 인수로 전달받은 프로퍼티 키가 객체의 고유의 프로퍼티 키인 경우에만 true를 반환하고 상속받은 프로토타입의 프로퍼티 키인 경우 false를 반환한다.

 

 

 

  • [19.14] 프로퍼티 열거
  • for ... in 문
  • 객체의 모든 프로퍼티를 순회하며 열거하려면 for ... in 문을 사용한다.
  • for (변수선언문 in 객체) { ... }
  • for ... in 문은 객체의 프로퍼티 개수만큼 순회하며 for ... in 문의 변수 선언문에서 선언한 변수에 프로퍼티키를 할당한다.
  • for ... in 문은 in 연산자처럼 순회 대상 객체의 프로퍼티뿐만 아니라 상속받은 프로토타입의 프로퍼티까지 열거한다.
  • for ... in 문은 객체의 프로토타입 체인 상에 존재하는 모든 프로토타입의 프로퍼티 중에서 프로퍼티 어트리뷰트 [[Enumerable]]의 값이 true인 프로퍼티를 순회하며 열거한다.
  • for ... in 문은 프로퍼티 키가 심벌인 프로퍼티는 열거하지 않는다.
  • Object.keys/values/entries 메서드
  • 객체 자신의 고유 프로퍼티만 열거하기 위해서는 for ... in 문을 사용하는 것보다 Object.keys/values/entries 메서드를 사용하는 것을 권장한다.
  • Object.keys 메서드는 객체 자신의 열거 가능한 프로퍼티 키를 배열로 반환한다.