なぜ2匹のハムスターがお腹一杯?
私たちは2匹のハムスターを持っています: speedy と lazy は一般的な hamster オブジェクトを継承しています。
そのうちの1匹に餌をやるとき、もう1匹もお腹一杯になります。なぜでしょう?どのように修正しますか?
let hamster = {
stomach: [],
eat(food) {
this.stomach.push(food);
}
};
let speedy = {
__proto__: hamster
};
let lazy = {
__proto__: hamster
};
// 一方が食べ物を見つけました
speedy.eat("apple");
alert( speedy.stomach ); // apple
// もう一方も持っています。なぜでしょう?修正してください。
alert( lazy.stomach ); // apple
呼び出し speedy.eat("apple") の中で何が起きているか注意深く見ていきましょう。
-
メソッド
speedy.eatはプロトタイプ(=hamster) で見つかり、this=speedy(ドットの前のオブジェクト)で実行されます。 -
次に、
this.stomach.push()はstomachプロパティを見つけ、pushする必要があります。それはthis(=speedy) の中でstomachを探しますが、見つかりません。 -
次に、プロトタイプチェーンに従って、
hamsterの中でstomachを見つけます。 -
そして、
pushを呼び出し、プロトタイプの stomach の中に食べ物を追加します。
従って、すべてのハムスターは1つの胃(stomach)を共有しています!
毎回、stomach はプロトタイプから取られ、stomach.push は “その場” で変更します。
シンプルな代入 this.stomach= の場合には、このようなことは起こらないことに注意してください。:
let hamster = {
stomach: [],
eat(food) {
// this.stomach.push の代わりに this.stomach に代入する
this.stomach = [food];
}
};
let speedy = {
__proto__: hamster
};
let lazy = {
__proto__: hamster
};
// Speedy は食べ物を見つけました
speedy.eat("apple");
alert( speedy.stomach ); // apple
// Lazy の胃は空っぽです
alert( lazy.stomach ); // <nothing>
今、すべてうまく行きました。なぜなら this.stomach= は stomach を参照しないからです。値は直接 this オブジェクトに書き込まれます。
また、各ハムスターが自身の胃をもつことで問題を避けることができます:
let hamster = {
stomach: [],
eat(food) {
this.stomach.push(food);
}
};
let speedy = {
__proto__: hamster,
stomach: []
};
let lazy = {
__proto__: hamster,
stomach: []
};
// Speedy one found the food
speedy.eat("apple");
alert( speedy.stomach ); // apple
// Lazy one's stomach is empty
alert( lazy.stomach ); // <nothing>
一般的な解決策として、上の stomach のような、特定のオブジェクトの状態を説明するすべてのプロパティは通常そのオブジェクトの中に書かれます。それはこのような問題を防ぎます。