失礼ながら、あなたはプロトタイプの振る舞いを誤解していました。
すべてを説明すると長すぎる話になりますが、プロトタイプに設定されたプロパティに関しては、インスタンスのプロパティを変更すると、すべてのインスタンスのこの値が変更されると、バグの無限の原因になります。
jsfiddle、jsbin、cssdeck、または好きなテストサイトを使用して、馬/犬の例を見てください。馬の色を変更しても、犬の色は変更されません。まだ黒いです。
どうしてこんなことに ?
dog のインスタンスがプロパティに対して READ アクセスを行うと、プロトタイプでシークされ、次にプロトタイプのプロトタイプでシークされ、プロトタイプのチェーンの最後に到達するまで続きます。最初に値が見つかった場合はそれが返され、プロトタイプでプロパティが見つからない場合は undefined が返されます。
したがって、インスタンスの作成直後は、すべての動物の色が null になります。
インスタンスのプロパティで WRITE アクセスを行うと、このインスタンスで新しいプロパティが作成され、指定された値が割り当てられます。このようにして、プロトタイプはその参照関数を保持し、インスタンスはその値を取得します。安心。
1) すべてのインスタンスがそれらのプロパティに有効な値 (デフォルト値) を提供することを保証します。
2)すべてのインスタンス間で共有される(静的)プロパティ(さらに重要なことに、大きなオブジェクト)を一度割り当てることで、メモリを節約できます。Expl : 犬のデフォルト画像。
3) すべてのインスタンスの値を一度に変更したい場合があります。この場合、プロトタイプの値を変更すると、まさにそれが行われます。
4) クラス (C++ の古典的な意味で) を JavaScript クラスに関連付けることで、JavaScript インタープリターがコードを最適化できるようにします。バックグラウンド クラスを使用してインスタンスを表現し続けます。パフォーマンスが重要な場合、それは非常に重要なポイントです。そうでない場合は、忘れてください:-)
ほんの小さな例です:動物を定義すると、各インスタンスにはその色と名前があります:プロトタイプではなく、コンストラクターでそれらを正しく設定することは理にかなっています。ただし、たとえば足の数については、インスタンスから別のインスタンスに変更されることはありません。また、子クラスを作成する場合は、子のプロトタイプの値をいつでも変更して、子クラスにこの数を変更させることができます。
function Animal(name, color) {
this.name = name;
this.color = null;
}
Animal.prototype.legCount = 4; // most animal have 4 legs (...)
// Dog Class, inheriting from Animal
function Dog(name) { Animal.apply(this, arguments); }
// Set Animal as Dog's prototype's prototype.
// so that we can safely change Dog's prototype.
Dog.prototype = Object.create(Animal.prototype);
// Duck class
function Duck(name) { Animal.apply(this, arguments); }
// same inheritance scheme
Duck.prototype = Object.create(Animal.prototype);
// ... but we change the legCount, for the ducks only
Duck.prototype.legCount = 2;
高度な回答:
インスタンスでこのプロパティに値を割り当てようとしても、プロトタイプ プロパティを変更しないでおきたい場合は、プロトタイプで読み取り専用プロパティとして設定します。
Object.defineProperty(Duck.prototype,'legCount', { get : function() { return 2 } } );
var duck = new Duck(...) ;
duck.legCount = 5;
console.log (duck.legCount) ; // --> output is still 2
インスタンスの値を設定してすべてのインスタンスの値を変更したい場合 (プロトタイプのプロパティ値を明示的に変更せずに)、プロトタイプのプロパティ定義のセッターで実行します。
// using a closure
var duckLegCount = 2;
Object.defineProperty(Duck.prototype,'legCount', {
get : function() { return duckLegCount } ,
set : function (x) { duckLegCount = x } } );
var duck1 = new Duck(...);
var duck2 = new Duck(...);
duck1.legCount = 12;
console.log ( duck2.legCount ) ; // output is 12