상속 (Inheritance)

프로토타입 상속

  • 자바스크립트 객체 간의 관계는 복사되는게 아니라 위임 연결이 맺어진 것
  • 전형적인 프로토타입 스타일 코드
function Foo(name) {
    this.name = name;
}

Foo.prototype.myName = function() {
    return this.name;
}

function Bar(name, label) {
    Foo.call(this, name);
    this.label = label;
}

Bar.prototype = Object.create(Foo.prototype); // 'Bar.prototype'를 'Foo.prototype'에 연결한다.

Bar.prototype.myLabel = funciton() {
    return this.label;
}

var a = new Bar("a", "obj a");
a.myName(); // "a"
a.myLabel(); // "obj a"

ES6 이전과 이후

// ES6 이전
Bar.prototype = Object.create(Foo.prototype); // 기존 'Bar.prototype'을 던져 버린다.

// ES6 이후
Object.setPrototypeOf(Bar.prototype, Foo.prototype); // 기존 'Bar.prototype'을 수정한다.

//polyfill
// Only works in Chrome and FireFox, does not work in IE:
Object.setPrototypeOf = Object.setPrototypeOf || function(obj, proto) {
  obj.__proto__ = proto;
  return obj; 
}

  • Object.create()를 쓰는 편이 사소하게 성능은 떨어지지만(던져 버린 객체를 나중에 가비지 콜렉트해야 하므로) 코드만 놓고 보면 ES6 이후 기법보다 오히려 더 짧고 가독성은 좋다.

클래스 관계 조사

  • 보통 전통적인 클래스 지향 언어에서는 인스턴스(자바스크립트에서는 객체)의 상속 계통Inheritance Ancestry(위임 링크)을 살펴보는 것을 인트로스펙션Introspection(리플렉션Reflection)이라고 한다.
function Foo() {
    // ...
}

Foo.prototype.blah = ...;

var a = new Foo();
a instanceof Foo; //true
  • 왼쪽에 일반 객체, 오른쪽에 함수를 피연산자로 둔 instanceof 연산자는 a의 [[Prototype]] 연쇄를 순회하면서 Foo.prototype가 가리키는 객체가 있는지 조사한다.
  • 이 말은 대상 함수(.prototype 레퍼런스가 붙은 Foo)에 대해 주어진 객체 a의 계통만 살펴볼 수 있다.
  • 2개의 객체 a, b가 있으면 instanceof 만으로는 두 객체가 서로 [[Prototype]] 연쇄를 통해 연결되어 있는지 알 수 없다.
Foo.prototype.isPrototypeOf(a); //true
  • Foo가 어떤 함수든 상관없이 다른 객체 테스트 시 사용할 객체(예제에선 Foo.prototype)만 있으면 된다.
  • isPrototypeOf()는 a의 전체 [[Prototype]] 연쇄에 Foo.prototype이 있는지 찾는다.
  • 다음과 같이 관계를 확인하고 싶은 객체를 2개 적어주기만 하면된다.
    // c의 [[Prototype]] 연쇄 어딘가에 b가 존재하는가
    b.isPrototypeOf(c);
    
  • ES5부터 지원하는 표준 메서드를 사용하면 다음과 같이 객체 [[Prototype]]을 곧바로 조회할 수도 있다.
    Object.getPrototypeOf(a) === Foo.prototype; //true
    
  • 거의 모든 브라우저에서 내부의 [[Prototype]]을 들여다볼 수 있는 비표준 접근 방법
    a.__proto__ === Foo.prototype; //true
    

Object.create()

Object.create = function(o) {
    function F(){}
    F.prototype = o;
    return new F();
};
  • 임시 함수 F를 이용하여 F.prototype 포로퍼티가 링크하려는 객체를 가리키도록 오버라이드한다.
  • 그런 다음 new F()로 원하는 연결이 수립된 새 객체를 반환한다.