Proč jsou oba křečci sytí?
Máme dva křečky: rychlý a líný, kteří jsou zděděni z obecného objektu křeček.
Když jednoho z nich nakrmíme, bude sytý i ten druhý. Proč? Jak to můžeme opravit?
let křeček = {
žaludek: [],
žer(potrava) {
this.žaludek.push(potrava);
}
};
let rychlý = {
__proto__: křeček
};
let líný = {
__proto__: křeček
};
// Tento křeček nalezl potravu
rychlý.žer("jablko");
alert( rychlý.žaludek ); // jablko
// Tento ji má také, proč? Opravte to, prosíme.
alert( líný.žaludek ); // jablko
Podívejme se pozorně na to, co se děje při volání rychlý.žer("jablko").
-
Metoda
rychlý.žerje nalezena v prototypu (=křeček) a pak se spustí sthis=rychlý(objekt před tečkou). -
Pak
this.žaludek.push()musí najít vlastnostžaludeka zavolat na nípush. Hledážaludekvthis(=rychlý), ale nic nenajde. -
Pak následuje řetězec prototypů a najde
žaludekv objektukřeček. -
Pak na něm volá
push, čímž přidá potravu do žaludku prototypu.
Všichni křečci tedy sdílejí jediný žaludek!
Jak pro líný.žaludek.push(...), tak pro rychlý.žaludek.push() je vlastnost žaludek nalezena v prototypu (protože není v samotném objektu) a pak jsou do ní vložena nová data.
Prosíme všimněte si, že při jednoduchém přiřazení this.žaludek= se to nestane:
let křeček = {
žaludek: [],
žer(potrava) {
// přiřazení do this.žaludek namísto this.žaludek.push
this.žaludek = [potrava];
}
};
let rychlý = {
__proto__: křeček
};
let líný = {
__proto__: křeček
};
// Rychlý křeček našel potravu
rychlý.žer("jablko");
alert( rychlý.žaludek ); // jablko
// Žaludek líného křečka je prázdný
alert( líný.žaludek ); // <nic>
Teď vše funguje správně, protože this.žaludek= nehledá žaludek, ale hodnota se zapíše přímo do objektu this.
Problému se můžeme zcela vyhnout i tak, že zajistíme, aby každý křeček měl svůj vlastní žaludek:
let křeček = {
žaludek: [],
žer(potrava) {
this.žaludek.push(potrava);
}
};
let rychlý = {
__proto__: křeček,
žaludek: []
};
let líný = {
__proto__: křeček,
žaludek: []
};
// Rychlý křeček našel potravu
rychlý.žer("jablko");
alert( rychlý.žaludek ); // jablko
// Žaludek líného křečka je prázdný
alert( líný.žaludek ); // <nic>
Běžné řešení je, že všechny vlastnosti, které popisují stav určitého objektu, jako třeba uvedený žaludek, by měly být zapisovány přímo do tohoto objektu. Tím předejdeme takovýmto problémům.