Trwa tłumaczenie tego artykułu.

Kiedy w poprzednim artykule budowałeś grę "Zgadnij numer", mogłeś stwierdzić, że ona po prostu nie działała. Nie martw się - ten artykuł ma na celu zatrzymanie cię przed wyrywaniem sobie włosów nad takimi problemami poprzez dostarczenie ci narzędzi do znajdowania i naprawienia błędów w programach napisanych w JavaScript.

Wymagania wstępne: Podstawowa znajomość obsługi komputera, podstawowe rozumenie HTML i CSS oraz wiedza, czym jest JavaScript.
Cel: Zdobycie umiejętności i odwagi do rozwiązywania prostych problemów w twoim własnym kodzie.

Typy błędów

Każdy błąd w kodzie można w ogólności podzielić na dwa typy:

  • Błędy składniowe:  Są to literówki w twoim kodzie, które albo sprawią, że program w ogóle się nie uruchomi, albo przestanie działać w pewnym momencie - zwykle zostaną podane także wiadomości o błędzie. Zwykle naprawa ich nie jest trudno, tak długo jak znasz odpowiednie narzędzia i wiesz, co znaczą poszczególne komunikaty błędów!
  • Błędy logiczne: Są to błedy, gdy składnia jest poprawna, ale kod zachowuje się inaczej niż chciałeś, aby to robił. Znaczy to, że program uruchamia się poprawnie, ale daje niepoprawne wyniki. Są to trudne błędy do naprawienia, gdyż często nie mają żadnej informacji, która by naprowadziła na źródło błędu.

No dobra, nie jest to tak proste - istnieją także inne czynniki, które różnicują błędy. Powyższa klasyfikacja wystarczy jednak w tym początkowym etapie twojej kariery. W kolejnej częsci przyjrzymy się tym dwóm typom błędów.

Błędogenny przykład

Zaczniemy od naszej poprzedniej gry "Zgadnij numer" - tylko że tym razem będziemy zajmować się wersją w której umyślnie ukryto trochę błędów. Odwiedź GitHub i wykonaj lokalną wersję  number-game-errors.html (Zobacz live demo tutaj).

  1. Aby zacząć, otwój lokalną wersję w swoim ulubionym edytorze tekstu i w twojej przeglądarce.
  2. Spróbuj zagrać w tę - odkryjesz że kiedy wciskasz przycisk "Zgadnij" - on po prostu nie działa!

Notatka: Równie dobrze możesz mieć swoją wersję gry, która ci nie działa. Wiemy, że może chciałbyś ją naprawić, ale chcemy, abyś wykorzystał naszą wersję, dzięki czemu nauczysz się technik, których tu uczymy. Następnie możesz  wykorzystać je do naprawienia własnego kodu.

W tym miejscu spójrzmy na narzędzia developerskie, dokładniej konsolę debugowania, aby sprawdzić, czy występują błędy składniowe, a jeżeli tak - naprawić je. Poniżej znajdują się instrukcje, jak tego dokonać.

Naprawa błędów składniowych

Wcześniej pokazaliśmy kilka prostych komend JavaScript, które wpisałeś do konsoli JavaScript w narzędziach deweloperskich (jeżeli nie pamiętasz jak je otworzyć, kliknij w link, aby sobie przypomnieć). Jej bardzo przydatną funkcją jest wyświetlanie błędów w momencie gdy interpreter JavaScript przeglądarki napotka na błąd. Wyruszmy na poszukiwanie błędów!

  1. Idź do karty z otwartą stroną number-game-errors.html i otwórz konsolę JavaScript. Znajdziesz tam błąd:
  2. Jest to prosty błąd do wytropienia, a przeglądarka daje wiele przydatnych  wskazówek: (powyższy screen jest z Firefoxa, ale inne przeglądarki pokazują podobne informacje). Od lewej do prawej znajdują się: 
    • Czerwony "x" dla pokazania, że jest to błąd.
    • Wiadomość błędu dla pokazania, co poszło nie tak: "TypeError: guessSubmit.addeventListener is not a function"
    • Link do "Learn More", który przekierowuje do strony na MDN, która wyjaśnia szczegółowo dany błąd.
    • Nazwa pliku JavaScript, która po kliknięciu kieruje do karty debuggera. Jeżeli klikniesz go, pokaże ci się dokładna linia z danym błędem.
    • Numer linii oraz znak, gdzie wystąpił błąd. W tym przypadku linia 86, znak 3.
  3. Spoglądając na linię 86, zobaczymy następujący kod:
    guessSubmit.addeventListener('click', checkGuess);
  4. The error message says "guessSubmit.addeventListener is not a function", so we've probably spelled something wrong. If you are not sure of the correct spelling of a piece of syntax, it is often good to look up the feature on MDN. The best way to do this currently is to search for "mdn name-of-feature" on your favourite search engine. Here's a shortcut to save you some time in this instance: addEventListener().
  5. So, looking at this page, the error appears to be that we've spelled the function name wrong! Remember that JavaScript is case sensitive, so any slight different in spelling or casing will cause an error. Changing addeventListener to addEventListener should fix this. Do this now.

Note: See our TypeError: "x" is not a function reference page for more details about this error.

Błędy składniowe - podejście drugie

  1. Zapisz stronę i odśwież - zobaczysz, że błąd zniknął.
  2. Spróbuj teraz wpisać liczbę. Po kliknięciu na przycisk "Wyślij" zobaczysz... inny błąd!
  3. Tym razem błąd to "TypeError: lowOrHi is null", on line 78.
    Notatka: Null jest specjalną wartością, która oznacza "nic" bądź "brak wartości" A więc lowOrHi został zadeklarowany i zainicjalizowany - ale wartością pustą.
    Notatka: Ten błąd pojawił się jak tylko strona została załadowana, dlatego że błąd wystąpił podczas wykonywania funkcji (w środku bloku checkGuess() { ... }). Jak dowiesz się później bardziej szczegółowo, kod wewnątrz funkcji jest wykonywany w innej przestrzeni niż kod poza funkcją. W tym przypadku kod nie został uruchomiony, a błąd wyrzucony do momentu, aż funkcja checkGuess() nie dotarła do linijki 86.
  4. Popatrz na linię 78. Zobaczysz tam następujący kod:
    lowOrHi.textContent = 'Last guess was too high!';
  5. W tej linii następuje próba ustawienia właściwości textContent zmiennej lowOrHi na tekst, ale to się nie powiodło ze względu na fakt, że lowOrHi nie jest tym, czego oczekujemy.  Trzeba się dowiedzieć, dlaczego tak jest - wyszukajmy inne wystąpienia lowOrHi. Najwcześniejsze wystąpienie znajdziemy w linii 48:
    var lowOrHi = document.querySelector('lowOrHi');
  6. W tej linii próbujemy przypisać zmiennej referencję do elementu w dokumencie HTML. Sprawdźmy, czy wartością tej zmiennej jest null po wykonaniu tej linijki. Aby to zrobić, dodaj ten kod w linii 49: 
    console.log(lowOrHi);

    Notatka: console.log() jest bardzo użyteczną funkcją do debugowania, której celem jest wypisanie wartości zmiennej do konsoli. W tym przypadku wypisze ona wartośćlowOrHi do konsoli w takiej postaci, w jakiej została ona ustawiona w linii 48.

  7. Zapisz plik i odśwież stronę. Po przejściu do konsoli zobaczysz efekt wywołania console.log().Możemy być pewni - w tym momencie wartością lowOrHi jest null. Oznacza to, że błąd jest zdecydowanie związany z linią 48.
  8. Pomyślmy - co może być tutaj problemem? W linii 48 używamy document.querySelector() aby otrzymać referencję do elementu. Odbywa się to poprzez podanie selektora CSS jako parametr funkcji. W dalszej częsci pliku można znaleźć paragraf, którego referencji potrzebujemy:
    <p class="lowOrHi"></p>
  9. To oznacza, że potrzebujemy tu selektora klasy. Zaczyna się on kropką (.) - ale selektor, którego używamy w querySelector() (linia 48) nie ma kropki. To może być nasz błąd! Spróbuj zmienić lowOrHi na .lowOrHi w linii 48.
  10. Zapisz i odśwież stronę. Teraz console.log() powinien wyświetlić element  <p>, którego poszukiwaliśmy. Uff! Kolejny błąd naprawiony! Możesz już usunąć linię z console.log() (albo zostawić ją odniesienie na później - jak uważasz).

Note: See our TypeError: "x" is (not) "y" reference page for more details about this error.

Syntax errors round three

  1. Now if you try playing the game through again, you should get more success — the game should play through absolutely fine, until you end the game, either by guessing the right number, or by running out of lives.
  2. At that point, the game fails again, and the same error is spat out that we got at the beginning — "TypeError: resetButton.addeventListener is not a function"! However, this time it's listed as coming from line 94.
  3. Looking at line number 94, it is easy to see that we've made the same mistake here. We again just need to change addeventListener to .addEventListener. Do this now.

A logic error

At this point, the game should play through fine, however after playing through a few times you'll undoubtedly notice that the "random" number you've got to guess is always 0 or 1. Definitely not quite how we want the game to play out!

There's definitely a problem in the game logic somewhere — the game is not returning an error; it just isn't playing right.

  1. Search for the randomNumber variable, and the lines where the random number is first set. The instance that stores the random number that we want to guess at the start of the game should be around line number 44:
    var randomNumber = Math.floor(Math.random()) + 1;
    And the one that generates the random number before each subsequent game is around line 113:
    randomNumber = Math.floor(Math.random()) + 1;
  2. To check whether these lines are indeed the problem, let's turn to our friend console.log() again — insert the following line directly below each of the above two lines:
    console.log(randomNumber);
  3. Save and refresh, then play a few games — you'll see that randomNumber is equal to 1 at each point where it is logged to the console.

Working through the logic

To fix this, let's consider how this line is working. First, we invoke Math.random(), which generates a random decimal number between 0 and 1, e.g. 0.5675493843.

Math.random()

Next, we pass the result of invoking Math.random() through Math.floor(), which rounds the number passed to it down to the nearest whole number. We then add 1 to that result:

Math.floor(Math.random()) + 1

Rounding a random decimal number between 0 and 1 down will always return 0, so adding 1 to it will always return 1.  We need to multiply the random number by 100 before we round it down. The following would give us a random number between 0 and 99:

Math.floor(Math.random()*100);

Hence us wanting to add 1, to give us a random number between 1 and 100:

Math.floor(Math.random()*100) + 1;

Try updating both lines like this, then save and refresh — the game should now play like we are intending it to!

Other common errors

There are other common errors you'll come across in your code. This section highlights most of them.

SyntaxError: missing ; before statement

This error generally means that you have missed a semi colon at the end of one of your lines of code, but it can sometimes be more cryptic. For example, if we change this line inside the checkGuess() function:

var userGuess = Number(guessField.value);

to

var userGuess === Number(guessField.value);

It throws this error because it thinks you are trying to do something different. You should make sure that you don't mix up the assignment operator (=) — which sets a variable to be equal to a value — with the strict equality operator (===), which tests whether one value is equal to another, and returns a true/false result.

Note: See our SyntaxError: missing ; before statement reference page for more details about this error.

The program always says you've won, regardless of the guess you enter

This could be another symptom of mixing up the assignment and strict equality operators. For example, if we were to change this line inside checkGuess():

if (userGuess === randomNumber) {

to

if (userGuess = randomNumber) {

the test would always return true, causing the program to report that the game has been won. Be careful!

SyntaxError: missing ) after argument list

This one is pretty simple — it generally means that you've missed the closing parenthesis off the end of a function/method call.

Note: See our SyntaxError: missing ) after argument list reference page for more details about this error.

SyntaxError: missing : after property id

This error usually relates to an incorrectly formed JavaScript object, but in this case we managed to get it by changing

function checkGuess() {

to

function checkGuess( {

This has caused the browser to think that we are trying to pass the contents of the function into the function as an argument. Be careful with those parentheses!

SyntaxError: missing } after function body

This is easy — it generally means that you've missed one of your curly braces from a function or conditional structure. We got this error by deleting one of the closing curly braces near the bottom of the checkGuess() function.

SyntaxError: expected expression, got 'string' or SyntaxError: unterminated string literal

These errors generally mean that you've missed off a string value's opening or closing quote mark. In the first error above, string would be replaced with the unexpected character(s) that the browser found instead of a quote mark at the start of a string. The second error means that the string has not been ended with a quote mark.

For all of these errors, think about how we tackled the examples we looked at in the walkthrough. When an error arises, look at the line number you are given, go to that line and see if you can spot what's wrong. Bear in mind that the error is not necessarily going to be on that line, and also that the error might not be caused by the exact same problem we cited above!

Note: See our SyntaxError: Unexpected token and SyntaxError: unterminated string literal reference pages for more details about these errors.

Summary

So there we have it, the basics of figuring out errors in simple JavaScript programs. It won't always be that simple to work out what's wrong in your code, but at least this will save you a few hours of sleep and allow you to progress a bit faster when things don't turn out right earlier on in your learning journey.

See also

  • There are many other types of errors that aren't listed here; we are compiling a reference that explains what they mean in detail — see the JavaScript error reference.
  • If you come across any errors in your code that you aren't sure how to fix after reading this article, you can get help! Ask on the Learning Area Discourse thread, or in the #mdn IRC channel on Mozilla IRC. Tell us what your error is, and we'll try to help you. A listing of your code would be useful as well.

 

In this module

 

Autorzy i etykiety dokumentu

Autorzy tej strony: mat-bi
Ostatnia aktualizacja: mat-bi,