Drobná chyba, kterou jsem udělal s konstruktéry

Ve kterém jsem si téměř nevšiml chyby

Podařilo se mi vystopovat jemnou, ale důležitou chybu, kterou jsem dělal, když jsem používal konstruktory s podtřídami a ručně nastavoval prototypy.

Zvažte následující kód (z implementace kámen-papír-nůžky):

function Player(){
  this.move = null;
}
Player.prototype.setMove = function(mv) {
  this.move = mv;
};

function HumanPlayer() {

}
HumanPlayer.prototype = new Player();

let player1 = new HumanPlayer();
let player2 = new HumanPlayer();

player1.setMove('paper');
console.log(player1.move, player2.move);
//paper null

I když chyba nakonec nebyla hlavním problémem, všimněte si, kde je původně uložena vlastnost move hráčů1 a hráče2 - objekt, na který odkazuje HumanPlayer.prototype - a tento objekt je sdílen všemi HumanPlayer objekty!

Oba hráči přistupují ke svým move vlastnost z Human.prototype - což znamená, že sdílejí this.move ! Potvrďte to kontrolou hodnoty move pomocí getPrototypeOf()

console.log(player1.hasOwnProperty('move'));
//false
console.log(Object.getPrototypeOf(player1).move);
//null
Object.getPrototypeOf(player2).move = 'paper';
console.log(player1.move);
//paper

Nejen player1 nemají vlastní přesunutí vlastnosti, nastavení player2.[[Prototype]].move na paper k němu přistupuje player1.move ! move ve skutečnosti nemáme definován jako individuální stav pro každou instanci HumanPlayer

Kupodivu program fungoval dobře - zvažte setMove() funkce:

Player.prototype.setMove = function(mv) {
  this.move = mv;
};

Při vyvolání této funkce pomocí player1.setMove('paper') , this odkazuje na hráče 1. Protože hráč1 nemá vlastní vlastnost move , jeden je vytvořen! Každý hráč zavolá setMove() , každý má nyní svůj vlastní move vlastnost a move na HumanPlayer.prototype se již nikdy nepoužije.

player1.setMove('rock');
player2.setMove('paper');
console.log(player1.move, player2.move);
//rock paper
console.log(Object.getPrototypeOf(player1).move);
//null

Tentokrát jsme měli štěstí. Jak to správně opravit?

function Player(){
  this.move = null;
}

function HumanPlayer() {
  Player.call(this);
}
HumanPlayer.prototype = new Player();

let player1 = new HumanPlayer();
let player2 = new HumanPlayer();

console.log(player1.hasOwnProperty('move'));
//true

Zaměřte se na HumanPlayer konstruktor - přidali jsme volání Player konstruktér. Nyní vytvoření nového HumanPlayeru vyvolá konstruktor Player (s použitím kontextu objektu, který byl poprvé vytvořen kvůli new ) a nastaví move vlastnost na tomto objektu. Nyní má každý hráč své vlastní vlastnosti. Se světem je vše v pořádku.