1

私は以下のプログラムを持っています

Object.prototype.inherit = function(baseConstructor) {
  this.prototype = (baseConstructor.prototype);
  this.prototype.constructor = this;
};
Object.prototype.method = function(name, func) {
  this.prototype[name] = func;
};

function StrangeArray(){}
StrangeArray.inherit(Array);
StrangeArray.method("push", function(value) {
  Array.prototype.push.call(this, value);
});

var strange = new StrangeArray();
strange.push(4);
alert(strange);

そしてそれを実行すると、スタックオーバーフローが発生しますか? なぜ?

4

3 に答える 3

6

に設定StrangeArray.prototypeしていArray.prototypeます。後で、pushメソッドを に追加しますStrangeArray.prototype(これは と同じですArray.prototype)。したがって、効果的に設定していますArray.prototype.push。メソッドpush呼び出しArray.prototype.push- つまり、それ自体。そのため、自分自身を繰り返し呼び出すだけで、スタックオーバーフローが発生します。

于 2009-08-09T11:54:54.313 に答える
2

ジョンは正しい。これを修正する方法があります。StrangeArray.prototypeをArray.prototypeに設定する代わりに、これによりStrangeArray.prototypeをArrayの新しいインスタンスに設定できるため、(Arrayのコンストラクターを呼び出さずに)Array.prototypeのプロパティを継承します。

Object.prototype.inherit = function(baseConstructor) {
  var tmp = Function();
  tmp.prototype = baseConstructor.prototype;
  this.prototype = new tmp();
  this.prototype.constructor = this;
};

編集:

this.prototype = new baseConstructor();

この例では機能しますが、より複雑なプログラムでは適切ではありません。基本コンストラクターがDOM要素の作成、カウントの増分、サーバーへの接続などの初期化を行う場合、その初期化はすべて、子オブジェクトがインスタンス化されるときではなく、スクリプトがロードされるときに行われます。

これに対処する別の方法は、コンストラクターで継承が呼び出されているか(プロトタイプに割り当てるため)、または単にインスタンス化するかを区別し、継承が呼び出されている場合は初期化を行わないことです。ただし、継承するときはコンストラクターを呼び出さないほうがいいので、継承するときはコンストラクターに空の関数を使用します。

私はこのことを説明するのが苦手です。Crockfordのサイトと、 Javascriptの継承に関するこれらの2つの記事をお勧めします。

于 2009-08-09T15:08:37.443 に答える
1

実際には、実際のオブジェクトのプロトタイプを baseConstructor の新しいインスタンスに設定するだけで済みます。

Object.prototype.inherit = function(baseConstructor) {
  this.prototype = new baseConstructor();
};

また、私が非常にきれいだと思ったこのプロトタイプの継承手法を見ていただくことをお勧めします。

于 2009-08-09T15:24:38.113 に答える