ハムスターが2匹、両方満腹なのはなぜですか?
「speedy」と「lazy」という2匹のハムスターがいます。これらは、一般的な「hamster」オブジェクトから継承されています。
どちらか1匹にエサをあげると、もう1匹も満腹になります。なぜですか?どのように修正できますか?
let
hamster =
{
stomach:
[
]
,
eat
(
food
)
{
this
.
stomach.
push
(
food)
;
}
}
;
let
speedy =
{
__proto__:
hamster
}
;
let
lazy =
{
__proto__:
hamster
}
;
// This one found the food
speedy.
eat
(
"apple"
)
;
alert
(
speedy.
stomach )
;
// apple
// This one also has it, why? fix please.
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を共有しています!
「lazy.stomach.push(...)」と「speedy.stomach.push()」の両方について、stomachプロパティはプロトタイプ(オブジェクト自体にはありません)で見つかり、新しいデータがそこへプッシュされます。
単純な代入「this.stomach=」の場合はこのようなことは起こらないことに注意してください。
let
hamster =
{
stomach:
[
]
,
eat
(
food
)
{
// assign to this.stomach instead of this.stomach.push
this
.
stomach =
[
food]
;
}
}
;
let
speedy =
{
__proto__:
hamster
}
;
let
lazy =
{
__proto__:
hamster
}
;
// Speedy one found the food
speedy.
eat
(
"apple"
)
;
alert
(
speedy.
stomach )
;
// apple
// Lazy one's stomach is empty
alert
(
lazy.
stomach )
;
// <nothing>
「this.stomach=」はstomachの検索を実行しないので、現在はすべてうまく動作します。値はthisオブジェクトに直接書き込まれます。
また、各ハムスターが自分のstomachを持つようにすることで、問題を完全に回避できます。
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のように特定のオブジェクトの状態を表すすべてのプロパティは、そのオブジェクト内に書き込む必要があります。これにより、このような問題が発生しません。