Wartości lokalne vs. dziedziczone

Wartości lokalne vs. dziedziczone

Gdy korzystasz z dostępu do własności obiektu, JavaScript wykonuje następujące kroki, tak jak opisano w poprzednim rozdziale:

  1. Sprawdza czy wartość istnieje lokalnie. Jeśli tak, to zwraca tę wartość.
  2. Jeśli wartość lokalna nie istnieje, sprawdza łańcuch prototypu (używając własności __proto__).
  3. Jeśli obiekt w łańcuchu prototypu posiada wartość dla określonej wartości, zwraca tę wartość.
  4. Jeśli własność ta nie została odnaleziona, to obiekt nie posiada tej własności.

Rezultat tych kroków zależy od sposobu, w jaki definiujesz rzeczy w kodzie. Oyginalny przykład używał następujących definicji:

function Employee () {
this.name = "";
this.dept = "general";
}

function WorkerBee () {
this.projects = [];
}
WorkerBee.prototype = new Employee;

Przypuśćmy, że wraz z tymi definicjami utworzyłeś amy jako instancję WorkerBee za pomocą poniższej instrukcji:

amy = new WorkerBee;

Obiekt amy posiada jedną lokalną własność, projects. Wartości własności name i dept nie są lokalne dla amy i dlatego są pobrane z własności __proto__ obiektu amy. W ten sposób amy posiada następujące wartości własności:

amy.name == "";
amy.dept = "general";
amy.projects == [];

Teraz przypuśćmy, że zmienisz wartość własności name w prototypie powiązanym z Employee:

Employee.prototype.name = "Unknown"

Na pierwszy rzut oka może Ci sie wydawać, że nowa wartość zostanie przekazana dalej do wszystkich instancji Employee. Nie dzieje się tak.

Gdy tworzysz dowolną instancję obiektu Employee, instancja ta otrzymuje lokalną wartość dla własności name (pusty ciąg znaków). Oznacza to, że gdy ustawisz prototyp WorkerBee poprzez utworzenie nowego obiektu Employee, WorkerBee.prototype posiada lokalną wartość dla własności name. Dlatego więc, gdy JavaScript sprawdza własność name obiektu amy (instancji WorkerBee), JavaScript znajduje lokalną wartość dla tej własności w WorkerBee.prototype. Dlatego też nie sprawdza on łańcucha dalej aż do Employee.prototype.

Jeśli chcesz zmienić wartość własności obiektu w momencie uruchomienia i sprawić, by była ona dziedziczona przez wszystkich potomków obiektu, nie możesz zdefiniować własności w funkcji konstruktora obiektu. Zamiast tego dodaj ją do prototypu powiązanego z konstruktorem. Na przykład, zakładając zmianę poprzedniego kodu na poniższy:

function Employee () {
   this.dept = "general";
}
Employee.prototype.name = "";

function WorkerBee () {
this.projects = [];
}
WorkerBee.prototype = new Employee;

amy = new WorkerBee;

Employee.prototype.name = "Unknown";

W tym wypadku własność name obiektu amy przyjmuje wartość "Unknown".

Jak pokazuję powyższe przykłady, jeśli chcesz zachować domyślne wartości dla własności obiektu i móc zmienić domyślne wartości w momencie uruchomienia, powinieneś utworzyć własności w prototypie konstruktora, a nie w samej funkcji konstruktora.

Autorzy i etykiety dokumentu

Autorzy tej strony: Ptak82, Diablownik, Mgjbot
Ostatnia aktualizacja: Diablownik,