2011-07-30 12 views
10

誰かが私にMe.prototype.constructor = Me;の使用を説明することはできますか?また、このコードが動作していなくても、なぜ必要なのでしょうか?JSでプロトタイプコンストラクタを使用

コードプロトタイプオブジェクトはMeオブジェクト上に作成され、インスタンス化されて古いプロトタイプオブジェクトに置き換えられます。なぜ私は指定されたコードで私のコンストラクタを指す必要がありますか?

function Me(){ 
    this.name = 'Dejan'; 

} 

function You(){ 
    this.name = 'Ivan'; 
} 

Me.prototype = new You(); 

somebody = new Me(); 

Me.prototype.constructor = Me; // Why? 

Me.prototype.foo = function(){ 
    alert('Proto Me!'); // It always fire up this alert, ether constructor is pointing to Me or not... ! 
} 

You.prototype.foo = function(){ 
    alert('Proto You!'); 
} 

somebody.foo(); 
alert(somebody.name); // Alert 'Dejan' 
+0

私は、レガシーブラウザが 'i​​nstanceof'キーワードの' .constructor'プロパティをチェックすると思います。 – Raynos

+0

2006年からの本です。 –

答えて

11

(instanceofは内部でプロトタイプチェーンをチェックし、constructorプロパティを必要としない)ことが必要ではない、それはでも人気の信念に反しinstanceofのために必要ではないです。通常、constructorは、コンストラクタのprototypeで本質的に列挙できないプロパティです。したがって、そのコンストラクタによってインスタンス化されたオブジェクトを与えると、そのコンストラクタを指す、列挙可能でないconstructorプロパティが返されます。

必要に応じて、理想的には列挙できないようにしておくとよいでしょう。いくつかのコードはオブジェクト上に.constructorの存在を仮定します。

あなたが投稿したコードでは、継承を行う際に、子プロトタイプとして動作するようインスタンス化したオブジェクトに、間違ったものを指し示すコンストラクタプロパティがあるため、コンストラクタをリセットする必要がありますコンストラクタ(コンストラクタ)

ES5では、あなたはどうなる:

Child.prototype = Object.create(Parent.prototype, { 
    constructor: { value: Child, enumerable: false } 
}); 

編集を:非標準__proto__を使用して継承を行う際にも、言及する価値があるかもしれない、それは__proto__は単に指定すると、オブジェクトのプロトタイプので、コンストラクタをリセットする必要はありませんそれは、それ自身のプロパティが存在しないときにルックアップが実行されるオブジェクトです。新しいprototypeには常にconstructorというプロパティがあります。

そうすることで:

var child = function() {}; 
child.prototype.__proto__ = parent.prototype; 

をあなたはchild.prototypeの基本constructorプロパティがまだそこにあるので、コンストラクタを設定する必要はありません。アクセスされた場合は、プロトタイプチェーンルックアップを実行する必要はありません。あなたは、あなたがそれを設定する前にそれを見つけるでしょう

console.log(Me.prototype.constructor); 
Me.prototype.constructor = Me; // Why? 

とライン

Me.prototype.constructor = Me; // Why? 

を交換する場合Me.prototypeYouのインスタンスであるため

+2

IE6は 'constructor'プロパティをチェックしていませんか? 'Object.create'はあなたのための' constructor'プロパティを設定します。あなたは手動でそれをする必要はありません – Raynos

+4

Raynos、いいえ私はIE6については本当に気にしないことを考えると、IE6についてはわかりません。また、Object.createはコンストラクタを設定しません。コンストラクタのコンセプトはありません。実際はObject.createのポイントです。親コンストラクタと等しいコンストラクタ・プロパティを取得するだけで、継承には間違いがあります。だからあなたはそれを変更する必要があります。 – chjj

+1

あなたの権利は私の 'コンストラクタ'について悪いです。 Object.createにコンストラクタの概念がありません – Raynos

5

Me.prototype.constructorが原因の行に、Youある

Me.prototype = new You(); 

したがって、th e // Why?このように継承を行ってJavaScriptを与えたという誤った印象を「修正」するにはコメントが必要です。


あなたは、古典的な継承を実装するために原型継承を使用しようとしているので、基本的に問題は約来ます。プロトタイプの継承はオブジェクトインスタンス上で動作し、 "クラス"や実際には "タイプ"という概念はありませんが、JavaScriptによって、new,.constructor、およびinstanceofのビジネス全体が混乱します。

この種のものを行うためのより多くの原型の方法は、パワーコンストラクタの賛成であなたが望む形でオブジェクトを返すつまり関数をコンストラクタを避けることです。

function begetPart(partNumber, description) { 
    return Object.create({}, { 
     number: { value: partNumber }, 
     description: { value: description }, 
     describe: { 
      value: function() { 
       alert(this.description); 
      } 
     } 
    }); 
} 

function begetTire(partNumber, speed) { 
    return Object.create(
     begetPart(partNumber, "A tire"), 
     { 
      speed: { value: speed }, 
      describe: { 
       value: function() { 
        alert(this.description + "; speed = " + this.speed); 
       } 
      } 
     } 
    ); 
} 

var genericPart = begetPart(1234, "A widget"); 
genericPart.describe(); // alerts "A widget" 

var tire = begetTire(4567, "fast"); 
tire.describe(); // alerts "A tire; speed = fast" 

ここでは言ってObject.createを使用」この他のオブジェクトインスタンスに基づいてオブジェクトインスタンスを作成します。もう1つのインスタンスはbegetPartの新しい空のオブジェクトで、一部のプロパティがbegetTireにあらかじめ埋められている新しい「パートインスタンス」です。

プロトタイプの継承オブジェクトインスタンスは、この「タイプ」または「クラス」のアイデアが途切れることなく、他のオブジェクトインスタンスから継承されるため、JavaScriptとプロトタイプの継承が実際にどのように機能するかが反映されます。

+0

'function Object(){[native code]}' – towry