본문 바로가기
Programming/JavaScript

Javascript - 내장 객체와 정적 메서드 상속

by Muko 2020. 6. 3.

내장 객체와 정적 메서드 상속

내장 객체는 Object.keys, Array.isArray 등의 자체 메서드를 갖는다.
그리고, ArrayObject 를 상속받듯이 네이티브 클래스들은 서로 상속 관계를 맺는다. 이렇게 한 클래스가 다른 클래스를 상속받으면 보통의 경우에는 정적 메서드와 그 외 메서드 모두를 상속받게 된다.

그런데 내장 클래스는 정적 메서드를 상속받지 못한다.
위의 이미지와 같이 ArrayDate 는 모두 Object 를 상속받기 때문에 두 클래스의 인스턴스에선 Object.prototype 에 구현된 메서드를 사용 가능하다. 그런데 Array.prototypeDate.prototypeObject 가 아니라 Object.prototype을 참조하기 때문에 Array.keys()Date.keys()와 같은 정적 메서드를 인스턴스에서 사용할 수 없다.

내장 객체 간의 상속과 extends 를 사용한 상속의 가장 큰 차이점이 여기에 있다.

내장 클래스 확장하기

extends를 사용하면 내장 클래스 간의 상속과 달리 정적 메서드까지 모두 상속 받는 것이 가능하다.

// 메서드 하나를 추가합니다(더 많이 추가하는 것도 가능).
class PowerArray extends Array {
  isEmpty() {
    return this.length === 0;
  }
}

let arr = new PowerArray(1, 2, 5, 10, 50);
alert(arr.isEmpty()); // false

let filteredArr = arr.filter(item => item >= 10);
alert(filteredArr); // 10, 50
alert(filteredArr.isEmpty()); // false

여기서 주목할 점은 filter, map 등의 내장 메서드가 상속받은 클래스인 PowerArray 의 인스턴스를 반환한다는 것이다.
따라서 arr.constructor === PowerArray 임을 확인할 수 있다.

그래서 arr.filter() 가 호출될 때는 기본 Array가 아니라 arr.constructor를 기반으로 새로운 배열이 만들어지는데, 이 때 PowerArray 에 구현되어 있는 메서드도 사용 가능하다.

만약 내장 메서드가 일반 배열을 반환하도록 하고 싶을 때는 특수 정적 getter인 Symbol.species 를 추가하면 된다.

class PowerArray extends Array {
  isEmpty() {
    return this.length === 0;
  }

  // 내장 메서드는 반환 값에 명시된 클래스를 생성자로 사용합니다.
  static get [Symbol.species]() {
    return Array;
  }
}

let arr = new PowerArray(1, 2, 5, 10, 50);
alert(arr.isEmpty()); // false

// filter는 arr.constructor[Symbol.species]를 생성자로 사용해 새로운 배열을 만듭니다.
let filteredArr = arr.filter(item => item >= 10);

// filteredArr는 PowerArray가 아닌 Array의 인스턴스입니다.
alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function

댓글0