2011-05-13 1 views
4

내가 왜 Boy.prototype = new Human;을 사용하여 상속을 시뮬레이션하는지 알 수 없습니다. 이봐, 우리가 원하는 건 함수의 권리 야? 우리는 새로운 A를 인스턴스화하지 않고 그것을 할 수 있습니다. (실제로 새로운 A를 인스턴스화하는 것은 우리가 원하지 않는 인스턴스화 함수를 실제로 실행한다는 의미에서 우리에게 바람직하지 않은 결과를줍니다)왜 우리는`Boy.prototype = new Human;`을 사용하여 상속을 시뮬레이트합니까?

더 나은 해결책?

for (var prop_name in Human.prototype) { 
Object.defineProperty(
      Boy.prototype, 
      prop_name, 
      Object.getOwnPropertyDescriptor(Human.prototype,prop_name) 
     ); 
} 

우리가 특정이며, 우리는 여전히 Object.getOwnPropertyNames를 사용하여 차례로 Object.getPrototypeOf을 통해 우리에게 사용할 수있는 프로토 타입 체인에 그것을 호출하여 그것을 달성 할 수 Human.prototype만을 열거 등록되지 싶은 말은.

우리가 더 좋은 옵션을 사용할 수있을 때 Boy.prototype = new Human;을 수행하면 유익을 얻을 수있는 이점이 정확히 무엇입니까?

답변

4

더 나은 옵션은 프로토 타입을 잡고 중간을 만드는 것입니다.

function extend(clazz, superclass) { 
    var intermediate = function() {}; 
    intermediate.prototype = superclass.prototype; 
    clazz.prototype = new intermediate(); 
    // Following line is optional, but useful 
    clazz.prototype.constructor = clazz; 
} 

이렇게하면 불필요한 복사를 피할 수 있지만 여전히 생성자에서 작업 할 개체를 인스턴스화 할 필요가 없습니다. 또한 instanceof를 사용할 수 있도록 프로토 타입 체인을 설정합니다. 또한 일부 상속 반 패턴이 수퍼 클래스 프로토 타입 오염을 일으키지 않습니다.

완벽을 기하기 위해 서브 클래스는 생성자에서 수퍼 클래스 생성자를 호출해야하며 Superclass.call(this);과 함께 할 수 있습니다.

편집 : ES5 때문에, 당신은 같은 일을

Subclass.prototype = Object.create(Superclass.prototype); 

extend에 전화를 교체 할 수 있습니다.

+0

'superclass'보다는 오히려 프로토 타입 체인에서'intermediate'라는 이름의 문제가 생깁니다. – Raynos

+0

정말로. 첫째로 'intermediate'라는 이름은 없습니다 (익명 생성자 함수입니다 - 중간은 확장 함수로 범위가 지정됩니다). 프로토 타입 체인에 여분의 객체가 있다는 사실을 고려해 볼 수도 있지만 실제로는 올바른 것으로 간주됩니다. 추가 객체는 하위 클래스 * 클래스 *를 나타냅니다. 그것 없이는, 서브 클래스 클래스를 나타내는 것은 아무것도 없다. 객체 자체는 인스턴스를 나타내며, 객체의 클래스는 프로토 타입 체인에 있어야합니다. – kybernetikos

+0

@ Adam 수퍼 클래스 객체가 체인에 남아있는 것은 맞습니다. 단, 수퍼 클래스와 clazz 사이의 중간을 제외하면됩니다. 이 패턴은 작은 체인에만 유용합니다. 이 패턴을 사용하여 4 번 체인하면 프로토 타입 체인에 8 개의 객체가 있습니다. 이렇게하면 탐색 시간이 크게 늘어나고 코드가 느려집니다. – Raynos

4
  • instanceofisPrototypeOf() 그것은 덜 장황의
  • 작동 함을 의미 올바르게 프로토 타입 체인을 설정

평소 초기화 할 때을 수행 생성자 함수를 방지하기 위해 간단하지만 추한 해결 방법이 있습니다 프로토 타입 객체를 만드는 데 그냥 사용하고 있습니다. 예를 들어, 인수 확인할 수 있습니다 중 하나

function Boy(name) { 
    if (arguments.length == 1) { 
     this.name = name; 
     // Do other initialization 
    } 
} 

을 ... 또는 명시 적으로 호출 할 수있는 별도의 방법으로 초기화를 이동 :

function Boy(name) {} 

Boy.prototype.init = function(name) { 
    this.name = name; 
    // Do other initialization 
} 

이 당신을 요구하는 명백한 단점이있다 새 Boy을 만들 때마다 init()에 전화하는 것을 잊지 마십시오.

ECMAScript 5 환경 (예 : 대부분의 브라우저의 최신 버전)에서는 ECMAScript 5의 Object.create()을 사용하면 다른 개체에서 직접 상속받은 개체를 만들고 프로토 타입 체인을 설정할 수 있습니다. 비 ES5 환경에서 : (Object.defineProperty in ES5?를 볼 수 있지만 약) :이 에뮬레이트 할 수

if (!Object.create) { 
    Object.create = function(o) { 
     function F() {} 
     F.prototype = o; 
     return new F(); 
    }; 
} 
+0

답변 상단에있는 이유는 정확하지만 때로는 문제를 해결하기위한 제안은 반 패턴을 고려해야 할 사항입니다. .prototype = new Superclass();를 찾으면. 문제를 일으키는 경우 올바른 대답은 내 답변에서 제공된 것과 같은 더 우수한 상속 시스템을 사용하거나 여러 라이브러리 중 하나에 구축 된 시스템 중 하나를 사용하는 것입니다. – kybernetikos

+0

@TimDown은'.constructor' 속성을 설정하여 instanceof와 isPrototypeOf를 수정합니까? – Raynos

+0

@Raynos : 아니요. 'constructor' 속성은 거의 쓸모가 없습니다. –