Pourquoi deux hamsters sont rassasiés ?
Nous avons deux hamsters: speedy
et lazy
héritant de l’objet général hamster
.
Lorsque nous nourrissons l’un d’eux, l’autre est également rassasié. Pourquoi ? Comment y remédier ?
let hamster = {
stomach: [],
eat(food) {
this.stomach.push(food);
}
};
let speedy = {
__proto__: hamster
};
let lazy = {
__proto__: hamster
};
// Celui-ci a trouvé la nourriture
speedy.eat("apple");
alert( speedy.stomach ); // apple
// Celui-ci l'a aussi, pourquoi ? Merci de corriger cela.
alert( lazy.stomach ); // apple
Examinons attentivement ce qui se passe dans l’appel speedy.eat("apple")
.
-
La méthode
speedy.eat
se trouve dans le prototype (=hamster
), puis exécutée avecthis=speedy
(l’objet avant le point). -
Ensuite,
this.stomach.push()
doit trouver la propriétéstomach
et appelerpush
dessus. Il cherchestomach
dansthis
(=speedy
), mais rien n’est trouvé. -
Ensuite, il suit la chaîne de prototypes et trouve
stomach
danshamster
. -
Ensuite, il appelle
push
dessus, en ajoutant la nourriture dans stomach du prototype.
Tous les hamsters partagent donc un seul estomac!
Tant pour lazy.stomach.push(...)
et speedy.stomach.push()
, la propriété stomach
se trouve dans le prototype (comme il est pas dans l’objet lui-même), alors les nouvelles données sont poussé dedans.
Veuillez noter qu’une telle chose ne se produit pas dans le cas d’une simple affectation this.stomach=
:
let hamster = {
stomach: [],
eat(food) {
// assigner à this.stomach au lieu de this.stomach.push
this.stomach = [food];
}
};
let speedy = {
__proto__: hamster
};
let lazy = {
__proto__: hamster
};
// Speedy a trouvé la nourriture
speedy.eat("apple");
alert( speedy.stomach ); // apple
// L'estomac de Lazy est vide
alert( lazy.stomach ); // <rien>
Maintenant, tout fonctionne bien, car this.stomach=
n’effectue pas de recherche de stomach
. La valeur est écrite directement dans l’objet this
.
Nous pouvons également éviter le problème en nous assurant que chaque hamster a son propre stomach :
let hamster = {
stomach: [],
eat(food) {
this.stomach.push(food);
}
};
let speedy = {
__proto__: hamster,
stomach: []
};
let lazy = {
__proto__: hamster,
stomach: []
};
// Speedy a trouvé la nourriture
speedy.eat("apple");
alert( speedy.stomach ); // apple
// L'estomac de Lazy est vide
alert( lazy.stomach ); // <rien>
En tant que solution commune, toutes les propriétés qui décrivent l’état d’un objet particulier, comme stomach
ci-dessus, devraient être écrits dans cet objet. Cela empêche de tels problèmes.