2016-02-17 7 views
5

Zbliżam się do nauki JavaScript z tła Ruby, więc mam pewne problemy ze zrozumieniem (i wyrażeniem tego w słowach), dlaczego mój kod nie daje wyników I potrzeba. Uruchomiłem to na pythontutor.com, aby zobaczyć krok po kroku, co się dzieje, i to potwierdza moje podejrzenia. Jednak nie jestem do końca pewien, dlaczego tak się dzieje.Funkcja i prototyp JavaScript - podstawowy problem z routingiem dzięki metodom wywoływania

Buduję termostat, który ma powrócić "zielony", gdy temperatura spadnie poniżej 18dC. W mojej przedostatniej linijce konsola.log ma wartość 17, co jest poprawne, jednak gdy zadzwonię pod numer thermostat.displayColor w ostatnim wierszu, nadal mówi się w kolorze żółtym. Kod kończy się tam i nie wraca przez this.displayColor = this.currentColor(), czego się spodziewam (ponieważ zrobił to podczas pierwszego uruchomienia, aby zdefiniować kolor początkowy jako "żółty"

Kod działa poprawnie i zwraca "zielony" jeśli zmienię kod na bezpośredni wywołanie metody prototypowej this.currentColor(), ale po prostu chcę wiedzieć, dlaczego nie pozwala mi to zrobić w sposób opisany poniżej:

Nie jestem pewien co do terminologii opisującej to problem, przepraszam z góry, bo mój tytuł nie jest dokładny.

var DEFAULT_TEMP = 20; 

function Thermostat(){ 
    this.temperature = DEFAULT_TEMP; 
    this.maxTemp = 25; 
    this.powerMode = 'on'; 
    this.displayColor = this.currentColor() 
}; 

Thermostat.prototype.downButton = function(){ 
    if (this.temperature === 10){ 
    throw new Error('temp cannot be lower than 10dC'); 
    }; 
    this.temperature --; 
}; 

Thermostat.prototype.currentColor = function() { 
    if ((this.temperature >= 18) && (this.temperature < 25)) { 
    return 'yellow' 
    } 
    else if (this.temperature < 18) { 
    return 'green' 
    } 

    else { 
    return 'red' 
    } 
}; 

var thermostat = new Thermostat(); 
for (var i = 1; i <= 3; i++) { 
     thermostat.downButton(); 
     }; 
console.log("spec file test green, temp should be 17 and is:" + thermostat.temperature) 
console.log(thermostat.displayColor); //this should be green, but it is yellow! 

Odpowiedz

3

Powinieneś zadzwonić metoda currentColor(), displayColor jest ustawiona tylko w konstruktorze (w którym to czasie temperatura wynosi 20) i nie jest aktualizowana, gdy zmienia się temperatura.

To może mieć sens, aby dodać ustawienie kolorów metody downButton:

Thermostat.prototype.downButton = function(){ 
    if (this.temperature === 10){ 
    throw new Error('temp cannot be lower than 10dC'); 
    }; 
    this.temperature --; 
    this.displayColor = this.currentColor(); 
}; 
+0

dziękuję Rob za szybką odpowiedź! Czy istnieje jakiś szczególny powód, dla którego displayColor jest ustawiany tylko raz (w punkcie inicjalizacji)? Chciałbym przeczytać więcej na ten temat, prawdopodobnie jest to naprawdę fundamentalna koncepcja, ale nie jestem pewien, jak zacząć szukać tego – ugotchi

+1

@ggwc za każdym razem, gdy tworzysz instancję, którą wywołujesz funkcję konstruktora. Jest to jedyny czas, w którym funkcja 'Thermostat()' jest wywoływana, dlatego 'displayColor()' jest wywoływana tylko raz – Sean

+1

@ggwc Bez problemu. Być może myślisz, że 'this.displayColor = this.currentColor()' zwiąże wartość 'displayColor' w pewien sposób, że zawsze wywołuje funkcję' currentColor', aby uzyskać jej wartość, ale tak się nie dzieje. Konstruktor ('function Thermostat() {...') jest wywoływany jeden raz podczas tworzenia 'new Thermostat()', a wartości ustawione w konstruktorze są statyczne, chyba że zostaną zaktualizowane przez inne funkcje składowe lub zewnętrznie. –

2

Jak mówi Rob, należy wywołać funkcję, która oblicza aktualny kolor. Oto jego propozycja wraz z kilkoma ulepszeniami do kodu:

function Thermostat() { 
 
    this.MIN_TEMP = 10; 
 
    this.MAX_TEMP = 25; 
 
    this.temperature = 20; 
 
} 
 

 
Thermostat.prototype.decreaseTemp = function() { 
 
    if (this.temperature > this.MIN_TEMP) this.temperature--; 
 
}; 
 
Thermostat.prototype.increaseTemp = function() { 
 
    if (this.temperature < this.MAX_TEMP) this.temperature++; 
 
}; 
 
Thermostat.prototype.currentColor = function() { 
 
    if (this.temperature < 18) return 'green'; 
 
    if (this.temperature < 25) return 'yellow'; 
 
    return 'red'; 
 
}; 
 

 
var thermostat = new Thermostat(); 
 
for (var i = 1; i <= 3; i++) { 
 
    thermostat.decreaseTemp(); 
 
} 
 

 
// no errors mean all assertions pass 
 
thermostat.temperature.should.equal(17); 
 
thermostat.currentColor().should.equal('green');
<script src="https://cdnjs.cloudflare.com/ajax/libs/should.js/8.2.2/should.min.js"></script>

Powiązane problemy