From 0addc466131101c9253e412f5712ae768c0b0acc Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Sat, 29 May 2021 22:17:36 +0900 Subject: Learn/JavaScript/First_steps/What_went_wrong を更新 (#901) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 2021/04/03 時点の英語版に同期 - 訳注マクロを削除 --- .../first_steps/what_went_wrong/index.html | 192 ++++++++++----------- 1 file changed, 95 insertions(+), 97 deletions(-) (limited to 'files/ja') diff --git a/files/ja/learn/javascript/first_steps/what_went_wrong/index.html b/files/ja/learn/javascript/first_steps/what_went_wrong/index.html index accce26c15..ac01d59e91 100644 --- a/files/ja/learn/javascript/first_steps/what_went_wrong/index.html +++ b/files/ja/learn/javascript/first_steps/what_went_wrong/index.html @@ -12,7 +12,7 @@ tags: - Learn - Tutorial - console.log - - 'l10n:priority' + - l10n:priority translation_of: Learn/JavaScript/First_steps/What_went_wrong ---
{{LearnSidebar}}
@@ -34,23 +34,23 @@ translation_of: Learn/JavaScript/First_steps/What_went_wrong -

エラーの種類

+

エラーの種類

コードに誤りがある場合、一般的に以下の 2 つのうち、どちらかの誤りであることがよくあります。

-

まあ、こんなに単純ではありません。もっと深く追及していくと違う種類のエラーも出てくることでしょう。しかし、見習いのうちは上の分類で十分です。上記2 つの種類のエラーについて見ていきましょう。

+

まあ、こんなに単純ではありません。もっと深く追及していくと違う種類のエラーも出てくることでしょう。しかし、見習いのうちは上の分類で十分です。上記の 2 つの種類のエラーについて見ていきましょう。

-

誤りの例

+

誤りの例

-

始めるにあたり、数字当て (今回は当たらない) ゲームに戻りましょう。わざとエラーになるバージョンを見ていきます。Github に行って number-game-errors.html をローカルにコピーしてください。(ライブ実行はこちらを見てください)

+

始めるにあたり、数字当て (今回は当たらない) ゲームに戻りましょう。わざとエラーになるバージョンを見ていきます。Github に行って number-game-errors.html をローカルにコピーしてください (ライブ実行はこちらを見てください)。

    -
  1. 始めるには、コピーしたファイルをお好みのテキストエディターとブラウザで開きます。
  2. +
  3. 始めるには、コピーしたファイルをお好みのテキストエディターとブラウザーで開きます。
  4. ゲームで遊んでみてください。気づきましたか。"予想を入力" ボタンを押しても動きません!
@@ -58,208 +58,206 @@ translation_of: Learn/JavaScript/First_steps/What_went_wrong

: もしかしたら、あなたにも直したいと思っているバージョンがあるかもしれませんね。ですが、まずはこちらで用意したバージョンを直してみてください。そうすれば、ここで教えるテクニックが身につきます。それから、あなた自身のプログラムに戻って直してみてください。

-

それでは、開発者コンソールで文法エラーがあるか調べてみましょう。それからエラーを修正します。どうやって修正すればいいかは今から教えます。

+

それでは、開発者コンソールで構文エラーがあるか調べてみましょう。それからエラーを修正します。どうやって修正すればいいかは今から教えます。

-

文法エラーを修正する

+

構文エラーを修正する

-

以前に開発者ツールの JavaScript コンソールで、簡単なコマンドを入力してもらったことがあったと思います。(思い出せなければ、リンクを見て開き方を調べてください。) コンソールの何が便利かといえば、ブラウザの JavaScript エンジンに読み込ませようとしている JavaScript コードに文法エラーがあれば、すべて教えてくれるのです。さあ、バグを潰していきましょう。

+

以前に開発者ツールの JavaScript コンソールで、簡単なコマンドを入力してもらったことがあったと思います (思い出せなければ、リンクを見て開き方を調べてください)。コンソールの何が便利かといえば、ブラウザーの JavaScript エンジンに読み込ませようとしている JavaScript コードに構文エラーがあれば、すべて教えてくれるのです。さあ、バグを潰していきましょう。

    -
  1. number-game-errors.html ファイルを開いているタブを選択して、JavaScript コンソールを開いてください。以下のメッセージが表示されていますね。
  2. -
  3. これは分かりやすいエラーです。ブラウザからもいくつか情報が出ています。(上のスクリーンショットは FireFox のものですが、他のブラウザでも同様の情報が表示されるでしょう。) 左から順に説明します。 +
  4. number-game-errors.html ファイルを開いているタブを選択して、JavaScript コンソールを開いてください。以下のメッセージが表示されていますね。
  5. +
  6. これは分かりやすいエラーです。ブラウザーからもいくつか情報が出ています (上のスクリーンショットは FireFox のものですが、他のブラウザーでも同様の情報が表示されるでしょう)。左から順に説明します。
    • 赤色の 「x」 ボタンはエラーがあることを示しています。
    • 「TypeError: guessSubmit.addeventListener is not a function」というエラーメッセージが、何が問題かを示しています。
    • 「Learn More」 のリンクがエラー内容についてもっと詳細に説明する MDN のページを指しています。
    • JavaScript のファイルの名前が出ています。このリンクをクリックすると、開発者ツールのデバッガータブで問題のあるファイルが開きます。ハイライトされているエラーの箇所が見えるでしょう。
    • -
    • エラーがある行の行番号と、最初の文字が始まる番号が出ています。上の例では 86行目の 3文字目です。
    • +
    • エラーがある行の行番号と、最初の文字が始まる番号が出ています。上の例では 86 行目の 3 文字目です。
  7. -
  8. テキストエディターで 86行目を見てみましょう。 -
    guessSubmit.addeventListener('click', checkGuess);
    +
  9. テキストエディターで 86 行目を見てみましょう。 +
    guessSubmit.addeventListener('click', checkGuess);
  10. -
  11. エラーでは、"guessSubmit.addeventListener is not a function" とあり、これは JavaScript インタープリタに呼び出している関数が認識されないという意味です。しばしば、このエラーメッセージは、スペルミスをしたということです。もし正しい綴りがわからなければ、MDN のサイトで使用している機能を調べてみてください。きっと見つかります。いつもはお好みの検索エンジンで「mdn 機能の名前」と検索してみるのがよいでしょう。今回は代わりに addEventListener() のリンクを張っておきます。
  12. -
  13. ページによると、関数の名前を間違えたみたいですね!JavaScript は大文字・小文字を区別しますので、ちょっとでも違うとエラーの原因になることを覚えておきましょう。それでは addeventListener を addEventListener に修正してエラーを直しましょう。
  14. +
  15. エラーでは、"guessSubmit.addeventListener is not a function" とあり、これは JavaScript インタープリターに呼び出している関数が認識されないという意味です。しばしば、このエラーメッセージは、スペルミスをしたということです。もし正しい綴りがわからなければ、MDN のサイトで使用している機能を調べてみてください。きっと見つかります。いつもはお好みの検索エンジンで「mdn 機能の名前」と検索してみるのがよいでしょう。今回は代わりに addEventListener() のリンクを張っておきます。
  16. +
  17. ページによると、関数の名前を間違えたみたいですね!JavaScript は大文字・小文字を区別しますので、ちょっとでも違うとエラーの原因になることを覚えておきましょう。それでは addeventListeneraddEventListener に修正してエラーを直しましょう。
-

: TypeError: "x" is not a function のリファレンスページで、このエラーに関する詳細な説明が見られます。

+

: TypeError: "x" is not a function のリファレンスページで、このエラーに関する詳細な説明が見られます。

-

文法エラーその 2

+

構文エラーその 2

    -
  1. ファイルを保存してブラウザを更新すると、エラーが消えています。
  2. -
  3. 予想を入力して、予想を入力ボタンを押してみると、...別のエラーが起きています!
  4. -
  5. 今回のエラーを見ると、78行目で"TypeError: lowOrHi is null"が起きています。 -
    : Null は「何もない」ことや「値がない」ことを表す特別な値です。つまり lowOrHi が宣言されて初期化されているけれど、意味のある値ではない — つまり型も値もないということです。
    +
  6. ファイルを保存してブラウザーを更新すると、エラーが消えています。
  7. +
  8. 予想を入力して、予想を入力ボタンを押してみると、...別のエラーが起きています!
  9. +
  10. 今回のエラーを見ると、 78 行目で"TypeError: lowOrHi is null"が起きています。 +
    : Null は「何もない」ことや「値がない」ことを表す特別な値です。つまり lowOrHi が宣言されて初期化されているけれど、意味のある値ではない — つまり型も値もないということです。
    -
    : このエラーは関数内部 (checkGuess() { ... } ブロックの中) で発生したため、ページを読み込んだだけでは出てきませんでした。後に続く関数の記事を読み進めていけば分かりますが、内側の関数のスコープは外側の関数のスコープとは異なります。今回のケースでは、86行目の checkGuess() 関数が実行されるまで実行されず、エラーも発生していませんでした。
    +
    : このエラーは関数内部 (checkGuess() { ... } ブロックの中) で発生したため、ページを読み込んだだけでは出てきませんでした。後に続く関数の記事を読み進めていけば分かりますが、内側の関数のスコープは外側の関数のスコープとは異なります。今回のケースでは、 86 行目の checkGuess() 関数が実行されるまで実行されず、エラーも発生していませんでした。
  11. -
  12. 78行目を見てください。以下のコードが書かれています。 -
    lowOrHi.textContent = '今の予想は大きすぎです!';
    +
  13. 78 行目を見てください。以下のコードが書かれています。 +
    lowOrHi.textContent = '今の予想は大きすぎです!';
  14. -
  15. この行は lowOrHi 定数の textContent プロパティに文字列を設定しようとしていますが、lowOrHi 定数に適切な値が設定されていないため上手く動きません。lowOrHi が使用されている箇所をコードのほかの部分から探してみましょう。最初に見つかるのは 48行目でしょう。 -
    const lowOrHi = document.querySelector('lowOrHi');
    +
  16. この行は lowOrHi 定数の textContent プロパティに文字列を設定しようとしていますが、lowOrHi 定数に適切な値が設定されていないため上手く動きません。lowOrHi が使用されている箇所をコードのほかの部分から探してみましょう。最初に見つかるのは 48 行目でしょう。 +
    const lowOrHi = document.querySelector('lowOrHi');
  17. -
  18. ここでは、HTML の要素を参照する変数を作ろうとしています。この行の後ろで、値が null になっているか確認するため以下のコードを直後の 49行目に追加します。 -
    console.log(lowOrHi);
    +
  19. ここでは、HTML の要素を参照する変数を作ろうとしています。この行の後ろで、値が null になっているか確認するため以下のコードを直後の 49 行目に追加します。 +
    console.log(lowOrHi);
    -

    : console.log() は値をコンソールに出力する、デバッグするときにとても便利な関数です。これで 48行目で lowOrHi にセットしたはずの値がコンソールに出力されるでしょう。

    +

    : console.log() は値をコンソールに出力する、デバッグするときにとても便利な関数です。これで 48行目で lowOrHi にセットしたはずの値がコンソールに出力されるでしょう。

  20. -
  21. ファイルを保存して再度ブラウザで読み込みます。そして console.log() の結果をコンソールで見てみましょう。 わかりましたね。lowOrHi の値は null でした。これで問題が 48行目にあることがわかりました。
  22. -
  23. それでは何が問題となり得るか考えてみましょう。48行目では要素への参照を CSS セレクタを使用して取得する document.querySelector() メソッドが使用されています。ファイルの少し上のほうにある、問題となる{{htmlelement("p")}} 要素を見てみましょう。 -
    <p class="lowOrHi"></p>
    +
  24. ファイルを保存して再度ブラウザーで読み込みます。そして console.log() の結果をコンソールで見てみましょう。 わかりましたね。lowOrHi の値は null でした。これで問題が 48 行目にあることがわかりました。
  25. +
  26. それでは何が問題となり得るか考えてみましょう。 48 行目では要素への参照を CSS セレクターを使用して取得する document.querySelector() メソッドが使用されています。ファイルの少し上のほうにある、問題となる{{htmlelement("p")}} 要素を見てみましょう。 +
    <p class="lowOrHi"></p>
  27. -
  28. ここではクラスセレクタが必要です。クラスセレクタはドット (.) で始まりますが、48行目で querySelector() メソッドに渡された文字列にはドットがありません。これが問題でしょう!48行目の lowOrHi を .lowOrHi に変更してみてください。
  29. -
  30. ファイルを保存して再度読み込むと、console.log() の文は求めていた <p> 要素を表示しています。何とか次のエラーを潰すことができました!console.log() の行は削除してもいいですし、後で使うために残しておいても大丈夫です。
  31. +
  32. ここではクラスセレクターが必要です。クラスセレクターはドット (.) で始まりますが、 48 行目で querySelector() メソッドに渡された文字列にはドットがありません。これが問題でしょう! 48 行目の lowOrHi.lowOrHi に変更してみてください。
  33. +
  34. ファイルを保存して再度読み込むと、console.log() の文は求めていた <p> 要素を表示しています。何とか次のエラーを潰すことができました!console.log() の行は削除してもいいですし、後で使うために残しておいても大丈夫です。
-

: TypeError: "x" is (not) "y"  のリファレンスページで、このエラーに関する詳細な説明が見られます。

+

: TypeError: "x" is (not) "y" のリファレンスページで、このエラーに関する詳細な説明が見られます。

-

文法エラーその 3

+

構文エラーその 3

  1. さて、もう一度ゲームをプレイしてみましょう。ゲームは問題なく動いているようです。正解するか、残りの予想回数がなくなって、ゲームが終わるまでは...。
  2. -
  3. ここで、またゲームが止まってしまいました。最初のエラーと同じく "TypeError: resetButton.addeventListener is not a function" というエラーです!しかし、今回は 94行目から発生していると表示されています。
  4. -
  5. 94行目を見ると、同じ間違いを犯したことがわかります。もう一度 addeventListener を .addEventListener に直してください。
  6. +
  7. ここで、またゲームが止まってしまいました。最初のエラーと同じく "TypeError: resetButton.addeventListener is not a function" というエラーです!しかし、今回は 94 行目から発生していると表示されています。
  8. +
  9. 94 行目を見ると、同じ間違いを犯したことがわかります。もう一度 addeventListener.addEventListener に直してください。
-

論理のエラー

+

論理エラー

今回はゲームは上手く動いているようです。しかし、何度か動かしていると、予想すべき「ランダムな」数字が常に 1 であることに気づくでしょう。これはあまりやりたくないゲームですね!

これはゲームのロジックに間違いなく問題があります。ゲームはエラーとはなっていませんが、正しく動いてはいません。

    -
  1. randomNumber 変数にランダムな数値が最初にセットされる場所を検索してみましょう。ゲームの開始で推測するランダムな数字を保存しようとしているのは 44行目のあたりです。 +
  2. randomNumber 変数にランダムな数値が最初にセットされる場所を検索してみましょう。ゲームの開始で推測するランダムな数字を保存しようとしているのは 44行目のあたりです。 -
    let randomNumber = Math.floor(Math.random()) + 1;
    - そして、それぞれのゲームの合間に次のランダムな数字を設定しているのは 113行目のあたりです。
  3. -
  4. -
    randomNumber = Math.floor(Math.random()) + 1;
    +
    let randomNumber = Math.floor(Math.random()) + 1;
  5. -
  6. これらの行が問題となるかを確認するため、console.log() にもう一度登場してもらいましょう。先ほどのそれぞれの行の直下に以下のコードを追加します。 -
    console.log(randomNumber);
    +
  7. そして、それぞれのゲームの合間に次のランダムな数字を設定しているのは 113 行目のあたりです。 +
    randomNumber = Math.floor(Math.random()) + 1;
  8. -
  9. 保存して再度読み込んで、何度かプレイしてみましょう。コンソールに出力される randomNumber の値が常に 1 であることに気づきます。
  10. +
  11. これらの行が問題となるかを確認するため、console.log() にもう一度登場してもらいましょう。先ほどのそれぞれの行の直下に以下のコードを追加します。 +
    console.log(randomNumber);
    +
  12. +
  13. 保存して再度読み込んで、何度かプレイしてみましょう。コンソールに出力される randomNumber の値が常に 1 であることに気づきます。
-

ロジックを何とかする

+

ロジックを修正する

-

これを直すには、この行が何をしているのか考えなければなりません。まず Math.random() を呼んでいます。これは 0 から 1 までのランダムな実数値を生成します。例えば 0.5675493843 などです。

+

これを直すには、この行が何をしているのか考えなければなりません。まず Math.random() を呼んでいます。これは 0 から 1 までのランダムな実数値を生成します。例えば 0.5675493843 などです。

-
Math.random()
+
Math.random()
-

次に Math.random() の実行結果を Math.floor() に渡して、一番近い整数に切り捨てています。そしてその結果に 1 を加えます。

+

次に Math.random() の実行結果を Math.floor() に渡して、一番近い整数に切り捨てています。そしてその結果に 1 を加えます。

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

0 から 1 のランダムな実数を切り捨てると、結果は常に 0 となり、それに 1 を加えることで常に 1 となります。ランダムな数を切り捨てる前に 100 を乗算しなければなりません。次のコードは 0 から 99 を返すでしょう。

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

さらに 1 を加えることで、1 から 100 のランダムな数字を返してくれるようになります。

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

先ほどの 2行をそれぞれ修正してください。保存して再度読み込むと、思い通りに動くようになっているでしょう!

+

先ほどの 2 行をそれぞれ修正してください。保存して再度読み込むと、思い通りに動くようになっているでしょう!

-

その他のよくあるエラー

+

その他のよくあるエラー

コードを書いていると、よくあるエラーは他にもあります。このセクションではそれらを紹介してみましょう。

-

SyntaxError: missing ; before statement

+

SyntaxError: missing ; before statement

-

たいてい、このエラーはコード行のどこかの末尾にセミコロン (;) がないことを意味しています。しかし、時にはかなり難解です。例えば checkGuess() 関数内の、この行を

+

たいてい、このエラーはコード行のどこかの末尾にセミコロン (;) がないことを意味しています。しかし、時にはもっと難解なこともあります。例えば checkGuess() 関数内のこの行を、

-
var userGuess = Number(guessField.value);
+
let userGuess = Number(guessField.value);

以下のように変更してみます。

-
var userGuess === Number(guessField.value);
+
let userGuess === Number(guessField.value);
-

そうすると、このエラーが吐かれます。違うことをやろうとしているように見えるのでしょう。値を変数にセットする代入演算子 (=) と、ある値が別の値と同じかどうかを判定して true または false を返す等値演算子 (===) を間違わないようにしてください。

+

そうすると、このエラーが吐かれます。違うことをやろうとしているように見えるのでしょう。値を変数に設定する代入演算子 (=) と、等値演算子 (===) を、これはある値が別の値と同じかどうかを判定して true または false を返しますが、間違わないようにしてください。

-

: SyntaxError: missing ; before statement  のリファレンスページで、このエラーに関する詳細な説明が見られます。

+

: SyntaxError: missing ; before statement のリファレンスページで、このエラーに関する詳細な説明が見られます。

-

プログラムが入力の内容に関わらずいつでも勝ちだと言ってくる

+

プログラムが入力の内容に関わらずいつでも勝ちだと言ってくる

-

これは代入と比較を混同する別の症状でしょう。たとえば、checkGuess() 関数内の、この行を

+

これは代入と比較を混同している別の症状でしょう。たとえば、checkGuess() 関数内の、この行を

-
if (userGuess === randomNumber) {
+
if (userGuess === randomNumber) {

以下のように変更してみます。

-
if (userGuess = randomNumber) {
+
if (userGuess = randomNumber) {
-

判定で常に true が返るようになり、常にプレイヤーが勝ったことになってしまいます。気を付けましょう!

+

判定で常に true が返るようになり、常にプレイヤーが勝ったことになってしまいます。気を付けましょう!

-

SyntaxError: missing ) after argument list

+

SyntaxError: missing ) after argument list

これは単純です。大体は関数やメソッドの呼び出しで閉じ括弧を忘れたことを表しています。

-

: SyntaxError: missing ) after argument list のリファレンスページで、このエラーに関する詳細な説明が見られます。

+

: SyntaxError: missing ) after argument list のリファレンスページで、このエラーに関する詳細な説明が見られます。

-

SyntaxError: missing : after property id

+

SyntaxError: missing : after property id

たいてい、このエラーは JavaScript のオブジェクトの書き方が正しくないことに関連しているのですが、

-
function checkGuess() {
+
function checkGuess() {

上記のコードを以下のように変えても起きるでしょう。

-
function checkGuess( {
+
function checkGuess( {
-

この変更でブラウザは関数の内容を関数の引数として渡しているように勘違いしてしまいます。括弧には気を付けましょう!

+

この変更でブラウザーは関数の内容を関数の引数として渡しているように勘違いしてしまいます。括弧には気を付けましょう!

-

SyntaxError: missing } after function body

+

SyntaxError: missing } after function body

-

これは簡単ですね。たいていの場合、関数や条件ブロックの終わりの閉じ波括弧が抜けていることを表します。checkGuess() 関数の最後の閉じ波括弧を消すと発生します。

+

これは簡単ですね。たいていの場合、関数や条件ブロックの終わりの閉じ波括弧が抜けていることを表します。checkGuess() 関数の最後の閉じ波括弧を消すと発生します。

-

SyntaxError: expected expression, got 'string' または SyntaxError: unterminated string literal

+

SyntaxError: expected expression, got 'string' または SyntaxError: unterminated string literal

-

これらのエラーは文字列の始まりもしくは終わりのクォーテーションマークが抜けていることを表します。最初のエラーは、文字列の始めのクォーテーションマークの代わりに、ブラウザが予期しない文字列を見つけた (string には実際に見つけた文字列が入ります) ことを表し、2 つ目のエラーは文字列がクォーテーションマークで終わっていないことを表します。

+

これらのエラーは文字列の始まりもしくは終わりの引用符が抜けていることを表します。最初のエラーは、文字列の始めの引用符の代わりに、ブラウザーが予期しない文字列を見つけた (string には実際に見つけた文字列が入ります) ことを表し、2 つ目のエラーは文字列が引用符で終わっていないことを表します。

どのエラーにも言えることですが、上の例でも見たように、考えてください。エラーが起きた時に、エラーが起きた行の番号をみて、その行にエラーがあるか見てみます。エラーはその行に存在しないこともありますし、上述した理由以外で起きることもあるということを心に留めておいてください。

-

: SyntaxError: Unexpected token と SyntaxError: unterminated string literal のリファレンスページで、これらエラーに関する詳細な説明が見られます。

+

: SyntaxError: Unexpected tokenSyntaxError: unterminated string literal のリファレンスページで、これらエラーに関する詳細な説明が見られます。

-

まとめ

+

まとめ

やっとここまで来ましたね。簡単な JavaScript プログラムのエラーを見つけ出すための基本が理解できました。コードの間違いを解決するのがいつも簡単とは限りませんが、特に学習の最初の過程では、うまくいかない時にも寝る時間を数時間節約し、多少早く進捗をあげられるでしょう。

-

あわせて参照

+

関連情報

-
-

{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}}

-

このモジュール内

+

このモジュール内

-- cgit v1.2.3-54-g00ecf