2012-04-27 3 views
1

프로토 타입 기반 상속을 통해 생성 된 클래스 계층 구조와 같은 것을 가지고있는 webapp에서 작업하고 있습니다. 공통 조상 "클래스"에 지속적으로 기능을 추가하여 생성자 서명이 지속적으로 확장되도록합니다.재귀 적으로 Javascript에서 "상위"생성자를 호출 하시겠습니까?

우리는 조상의 서명을 변경할 때마다 변경 사항을 생성자의 생성자에 전파해야합니다. 이것은 유지 관리 문제이므로 분명히 arguments 개체에서 부모에 대한 인수를 추출하고 Function.apply()을 사용하여 부모를 호출하는 함수를 만들었습니다.

코드는 다음과 같습니다

BaseClass.prototype._super = function(args) { 
    args = Array.prototype.slice.call(args, this.constructor.length); 
    this.parentConstructor.apply(this, args); 
}; 

과 같이 사용 :

function Child(child_arg1, child_arg2 /*, implicit parent args */) { 
    this._super(arguments); 
} 

(코드가 엄격 모드이기 때문에 내가 arguments.caller.arguments을 사용할 수 없습니다 this.parentConstructor 함수에 의해 설정된다. 클래스 계층 구조 만들기.

불행히도 이것은 한 수준의 상속에서만 작동합니다. 예를 들어, A의 부모 클래스 B는 자신의 부모 클래스 C를 가지고 있습니다. B가 _super을 호출하면 this.parentConstructor은 B를 계속 가리 킵니다. 이는 B가 무한 루프에서 자신을 호출하게된다는 것을 의미합니다.

parentConstructor 필드를 생성자 함수 객체 (프로토 타입 대신)와 함께 저장하면 현재 호출 함수를 전달해야합니다. 이것은 슈퍼 함수를 ​​주변 함수와 밀접하게 연결하는 선을 만들려고합니다.

아무도 더 좋은 방법을 알고 있습니까?

+0

"주변 기능과 매우 밀접하게 결합 된"이란 무엇을 의미합니까? 'Child' 생성자로부터'this._super (Child, arguments)'를 호출하는 것은 문제가되지 않을 것입니다, 그렇죠? – Bergi

+0

변경하지 않고도 모든 하위 생성자에 동일한 코드 행을 복사하여 붙여 넣을 수 있기를 바랍니다. 자바에서 할 수있는 것처럼 ... –

답변

0

나는 며칠 전 a related question에게 물었고 Kamyar Nazeri's answer은 나를 많이 도왔다.

문제를 피하는 방법은 항상 올바른 부모 개체를 참조하도록 새 생성자가 정의 된 클로저에 _super을 정의하는 것입니다. 다음 패턴은 아주 잘 날 위해 일했다 : 이전 버전의 브라우저를 위해 당신이 Object.create()Object.getPrototypeOf()에 대한 shims를 제공해야한다는

var BaseClass = 
{ 
    create: function() // Basically a constructor 
    { 
     var obj = Object.create({}); 

     obj.someProperty = "initial value based on arguments"; 

     return obj; 
    }; 
}; 

var Child = (function buildChild(){ 
    var obj = BaseClass.create("some value", "another argument") 
    , _super = Object.getPrototypeOf(obj); 

    // override BaseClass.create() 
    obj.create = function() 
    { 
     var obj = _super.create.apply(this, arguments); 

     // Child specific initializations go here 

     return obj; 
    }; 

    return obj; 
})(); // note that this gets called right away 

var c = Child.create("some argument", "another thing"); 

console.log(BaseClass.isPrototypeOf(c)); // true 

참고. this ECMAScript 5 shim이 도움이된다는 것을 발견했습니다. 나는 일반적으로 내가 사용하고있는 심을 뽑을 뿐이다.

+0

불행히도 이것은 피하려고 노력한 것입니다. 나는 함수를 사용하여 객체를 생성하는 아이디어를 좋아하지 않는다. 그것은 jsdoc을 매우 어색하게 만들고 가난한 Eclipse를 혼란스럽게 만듭니다 ... –

+0

그러면 유일한 방법은 상위 프로토 타입의 실제 이름을 사용하는 것입니다. 왜 객체를 생성하는 함수를 사용하는 _idea_가 당신에게 버그가됩니까? – donut

+0

이 프로그래밍 방식은 인간뿐만 아니라 문서 생성기 및 컴파일러 최적화에있어 매우 모호하고 혼란 스럽다고 생각합니다. 또한 이런 식으로 프로그래밍함으로써 "클래스"객체 중 실제 클래스가 없기 때문에'instanceof' 연산자와 다른 많은 도구들이 작동하지 않습니다. –

관련 문제