Odpowiedź @Patryk27 wyjaśnia jak obejść Twój problem, który jasno wynika z niezrozueminia jak działa bound context w JS'ie; więc wyjaśnię jak to działa i jaki był początkowy zamysł za tym pomysłem.
Spodziewałem się, że będzie wskazywał na objekt window
, tak jak się to dzieje, kiedy tworzę obiekt bez klasy.
Tylko że tam dostałeś window
, w konkretnym przypadku, bo w Twoim przykładzie scope to faktycznie window
. Gdybyś był w innym scopie, dostałbyś coś innego. Więc to nie jest tak, że to "zawsze" jest window
.
Dlaczego po zapisaniu referencji obj.speak
(instancja klasy) do zmiennej speak
, this
ma wartość undefined.
Krótka odpowiedź - bo nie zdefiniowałeś kontekstu.
Długa odpowiedź - below
Mamy takie dwie klasy.
class Square {
constructor(wysokosc) {
this.wysokosc = wysokosc;
}
printHeight() {
const figura = this;
console.log("Wysokość figury to " + figura.wysokosc);
}
}
class Rectangle {
constructor(wysokosc, szerokosc) {
this.wysokosc = wysokosc;
this.szerokosc = szerokosc;
}
}
I teraz zagadka
const square = new Square(5);
const rectangle = new Rectangle(13, 17);
rectangle.printHeight = square.printHeight;
rectangle.printHeight(); // jak myślisz, co tu będzie? Wysokość kwadratu, czy prostokąta? ;)
PS: Odpowiedź brzmi: square.printHeight()
wypisze wysokość kwadratu, a rectangle.printhHeight()
wysokość prostokąta.
PS: Jeśli ten przykład również wydaje Ci się bez sensu, to pamiętaj że JavaScript od początku był językiem prototypowanym, więc oczywiście nastawienie na funkcje jest większe, niż zastawienie na dane.
rectangle.printHeight = square.printHeight; // ten kod nie może kopiować "this";
Rectangle.prototype.printHeight = Square.prototype.printHeight; // żeby ten kod mógł poprawnie edytować prototyp