2

私の質問は、親オブジェクトのプロトタイプ チェーンを維持する子オブジェクトに関するものです。

John Resig の Advanced Javascript スライド ( http://ejohn.org/apps/learn/#76 ) で、子オブジェクトのプロトタイプ チェーンを維持するには、新しい親オブジェクトをインスタンス化する必要があると書いています。

しかし、いくつかの簡単なテストを通じて、子オブジェクトのプロトタイプを親オブジェクトのプロトタイプと等しく設定するだけで、プロトタイプ チェーンが維持されることに気付きました。

説明をいただければ幸いです。

オリジナルコード

function Person(){}
Person.prototype.dance = function(){};

function Ninja(){}

// Achieve similar, but non-inheritable, results
Ninja.prototype = Person.prototype;
Ninja.prototype = { dance: Person.prototype.dance };

assert( (new Ninja()) instanceof Person, "Will fail with bad prototype chain." );

// Only this maintains the prototype chain
Ninja.prototype = new Person();

var ninja = new Ninja();
assert( ninja instanceof Ninja, "ninja receives functionality from the Ninja prototype" );
assert( ninja instanceof Person, "... and the Person prototype" );
assert( ninja instanceof Object, "... and the Object prototype" );

私の修正版

function Person(){}
Person.prototype.dance = function(){console.log("Dance")};

function Ninja(){}

// Achieve similar, but non-inheritable, results
Ninja.prototype = Person.prototype;

assert( (new Ninja()) instanceof Person, "Will fail with bad prototype chain." );

var ninja = new Ninja();
assert( ninja instanceof Ninja, "ninja receives functionality from the Ninja prototype" );
assert( ninja instanceof Person, "... and the Person prototype" );
assert( ninja instanceof Object, "... and the Object prototype" );
ninja.dance();
4

2 に答える 2

8

John Resig が提供したコードでは、最初に に設定Ninja.prototypePerson.prototypeます。それから彼はすぐにそれを次のようにリセットします{ dance: Person.prototype.dance }:

// Achieve similar, but non-inheritable, results
Ninja.prototype = Person.prototype;
Ninja.prototype = { dance: Person.prototype.dance };

その結果、コンストラクターによって作成されたオブジェクトは、 のインスタンスではないものNinjaから直接継承されます。したがって、false を返します。この場合、プロトタイプ チェーンは次のようになります。{ dance: Person.prototype.dance }Person.prototype(new Ninja) instanceof Person

        null
         ^
         |
         | [[prototype]]
         |
+------------------+
| Object.prototype |
+------------------+
         ^
         |
         | [[prototype]]
         |
+------------------+
|  Ninja.prototype |
+------------------+
         ^
         |
         | [[prototype]]
         |
+------------------+
|     new Ninja    |
+------------------+

変更されたバージョンでは、2 番目の割り当てを に削除しNinja.prototype、実質的に に設定Ninja.prototypePerson.prototypeます。したがって、プロトタイプチェーンは次のとおりです。

         null
          ^
          |
          | [[prototype]]
          |
+-------------------+
|  Object.prototype |
+-------------------+
          ^
          |
          | [[prototype]]
          |
+-------------------+
| Ninja.prototype / |
| Person.prototype  |
+-------------------+
          ^
          |
          | [[prototype]]
          |
+-------------------+
|     new Ninja     |
+-------------------+

since はbothとNinja.prototype同じであり、を返すことに注意してください。これは、演算子がコンストラクターの に依存しているためです。Person.prototype(new Ninja) intanceof Ninja(new Ninja) instanceof Persontrueinstanceofprototype

ただし、JavaScript で継承を実現する正しい方法は、に設定Ninja.prototypeすることですObject.create(Person.prototype)(または古い学校の方法ではに設定しますnew Person)。この場合、プロトタイプ チェーンは次のようになります。

        null
         ^
         |
         | [[prototype]]
         |
+------------------+
| Object.prototype |
+------------------+
         ^
         |
         | [[prototype]]
         |
+------------------+
| Person.prototype |
+------------------+
         ^
         |
         | [[prototype]]
         |
+------------------+
|  Ninja.prototype |
+------------------+
         ^
         |
         | [[prototype]]
         |
+------------------+
|     new Ninja    |
+------------------+

注: JavaScript では、オブジェクトは他のオブジェクトから継承されることを常に覚えておいてください。コンストラクター関数から継承することはありません。JavaScript での真のプロトタイプ継承について学びたい場合は、プロトタイプの継承が重要である理由に関する私のブログ投稿をお読みください。

于 2013-07-21T02:45:04.223 に答える