1

プロトタイプベースの継承によって作成されたクラス階層のようなものを持つ webapp に取り組んでいます。共通の先祖「クラス」に機能を常に追加しているため、そのコンストラクターの署名は常に拡張されています。

祖先の署名を変更するたびに、子孫のコンストラクターにも変更を伝達する必要があります。これは明らかに保守性の問題であるため、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。クラス階層を構築する関数で設定されます。)

残念ながら、これは 1 レベルの継承でしか機能しません。たとえば、A の親クラス B が独自の親クラス C を持っている場合、B が を呼び出すと_super、 はthis.parentConstructor依然として B を指します。つまり、B は無限ループで自分自身を呼び出すことになります。

(プロトタイプではなく) コンストラクターの Functions オブジェクトと共に parentConstructor フィールドを格納する場合、現在の呼び出し関数を渡す必要があります。これにより、行呼び出しが周囲の関数に非常に密接に結合されますが、これは回避しようとしています。

したがって、誰かがより良い方法を知っていますか?

4

1 に答える 1

0

数日前に関連する質問をしましたが、 Kamyar Nazeri の回答がとても役に立ちました。

問題を回避する方法は_super、新しいコンストラクターが定義されているクロージャーで定義して、常に正しい親オブジェクトを参照するようにすることです。次のパターンは私にとって非常にうまく機能しました。

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

古いブラウザでは、とにshimを提供する必要があることに注意してください。この ECMAScript 5 shimが役立つことがわかりました。私は通常、使用しているシムのみを引き出します。Object.create()Object.getPrototypeOf()

于 2012-05-17T16:41:02.143 に答える