エラーを読んでみる
このレッスンで分かること
- エラーは「種類」「説明」「ファイル名と行番号」の 3 点セットで読みます
- よく出るのは
ReferenceErrorSyntaxErrorTypeErrorの 3 つです- 最小例は
function errorType(message) { return message.split(":")[0]; }
エラーを読んでみる とは
コンソールに出る赤いメッセージの読み方を覚えます。エラーの種類と行番号から、直す場所を自分で見つけられるようになります。
エラーは敵ではない
コードを書くと必ずエラーが出ます。ベテランでも 1 日に何十回も出します。違いは、出た瞬間に読むか、見ないふりをして当てずっぽうで直すかだけです。エラーメッセージは「どこが」「どう」おかしいかを教えてくれる、いちばん親切なヒントです。
コンソールに出るエラーは、次のような形をしています。
Uncaught ReferenceError: userName is not defined
at startupMessage (script.js:5:10)
at script.js:12:1分解すると 3 つの情報が入っています。
| 部分 | 内容 | この例では |
|---|---|---|
| エラーの種類 | どんな種類の失敗か | ReferenceError |
| 説明 | 何が起きたか | userName is not defined |
| 発生場所 | ファイル名と行と桁 | script.js:5:10 |
読む順番はこの表の下から上です。まず script.js の 5 行目を開き、そのあたりで userName という名前を探します。桁の 10 は行の中の何文字目かを表します。at から始まる行が複数あるのは、関数がどこから呼ばれたかをさかのぼって示しているためで、これをスタックトレースと呼びます。いちばん上が、実際に落ちた場所です。
Uncaughtは「誰も受け止めなかった」という意味です。第 10 章より先で学ぶtryを使うとエラーを受け止められますが、入門のうちは無視して構いません。読むのは種類と説明と行番号の 3 点です。
よく出る 3 つの種類
エラーの種類は名前を見ただけで原因の見当が付きます。まずは 3 つ覚えます。
| 種類 | 意味 | 代表的な原因 |
|---|---|---|
ReferenceError | その名前が見つからない | 変数名のつづり間違い、定義前の使用 |
SyntaxError | 文法として読めない | カッコやクォートの閉じ忘れ |
TypeError | 型が合わないので操作できない | undefined の中身を取ろうとした |
ReferenceError
存在しない名前を使ったときに出ます。多くはただのタイプミスです。
function startupMessage() {
return "こんにちは、" + userName;
}Uncaught ReferenceError: userName is not defined
at startupMessage (script.js:2:29)is not defined は「そんな名前は定義されていない」という意味です。user_name と書いたつもりが userName になっていた、というような大文字小文字の違いでも起きます。JavaScript は大文字と小文字を別物として扱います。
SyntaxError
文法として成立していないときに出ます。プログラムを実行する前の読み取り段階で止まるため、そのファイルの処理は 1 行も動きません。
function startupMessage(name) {
return "こんにちは、" + name;Uncaught SyntaxError: Unexpected end of input
at script.js:3:1Unexpected end of input は「まだ閉じていないのにファイルが終わった」という意味です。閉じカッコの不足が代表例です。この種類のエラーは、示された行そのものではなく、その少し前に原因があることが多いので、上へさかのぼって探します。
SyntaxErrorが出たとき、行番号はファイルの末尾を指しがちです。「最後まで読んだけど閉じられていなかった」ことに気づくのが末尾だからです。行番号を鵜呑みにせず、対応するカッコを上へたどってください。
TypeError
名前は存在するけれど、その値に対してできない操作をしたときに出ます。
function firstWorkTitle(works) {
return works[0].title;
}
firstWorkTitle();Uncaught TypeError: Cannot read properties of undefined (reading '0')
at firstWorkTitle (script.js:2:15)Cannot read properties of undefined は「undefined の中身は取り出せない」という意味です。引数を渡し忘れた、関数が return を書き忘れていて undefined が返ってきた、といった原因が典型です。カッコの中の reading '0' が、何を取ろうとしたのかを教えてくれます。
わざと壊して確かめる
エラーは待っていても来ません。自分から出しにいくのが、いちばん早い練習です。script.js に次の 3 つを順番に書いて、コンソールに何が出るか見てください。
console.log(userName);
console.log("こんにちは、" + name;
console.log(undefined.title);1 つ目は ReferenceError、2 つ目は SyntaxError、3 つ目は TypeError です。順番に試すつもりでも、2 つ目を書いた時点でファイル全体が SyntaxError で止まるため、1 つ目のメッセージは出ません。文法エラーは実行前に判定される、という違いをここで体感できます。
| 種類 | いつ判定されるか | 他の行への影響 |
|---|---|---|
SyntaxError | 実行する前 | ファイル全体が動かない |
ReferenceError | 実行中 | その行で止まる。前の行までは動く |
TypeError | 実行中 | その行で止まる。前の行までは動く |
この表の違いは重要です。console.log を仕込んだのに何も出ないときは、たいてい SyntaxError でファイルごと止まっています。まずコンソールの一番上まで戻って、赤い行を探してください。
課題では種類を取り出す
今回の課題は、エラーメッセージの文字列を受け取って、先頭の種類だけを返す関数です。メッセージは ReferenceError: userName is not defined のように、種類のあとに半角コロンが来る形で統一されています。つまり、コロンより前を切り出せば種類が取れます。
function errorType(message) {
return message.split(":")[0];
}
console.log(errorType("TypeError: Cannot read properties of undefined"));
// => TypeErrorsplit は文字列を指定した記号で区切って配列にするメソッドです。配列は第 5 章で詳しく扱いますが、ここでは [0] と書くと「区切った 1 つ目」が取れる、とだけ覚えておけば足ります。
実務では、エラーの文字列をそのまま検索窓に貼るのがいちばん速い解決法です。ただし自分のファイル名や変数名が入った部分は消してから検索してください。
Cannot read properties of undefinedのような共通部分だけを残すと、同じ症状の記事が見つかります。
よくある間違い
- エラーを読まずに書き直す — 赤い文字を見た瞬間に閉じてしまい、勘で直そうとするパターンです。まず種類と行番号を声に出して読みます
// 誤り。works が undefined でも気づかないまま書き換え続ける
return works[0].title;- 行番号だけを見て前後を見ない — とくに
SyntaxErrorは、原因が示された行より前にあります。カッコとクォートの対応を上へたどります
// 3 行目でエラーと出るが、原因は 2 行目の閉じカッコ不足
function startupMessage(name) {
return "こんにちは、" + name;- 大文字と小文字を同じだと思う —
userNameとusernameは別の名前です。ReferenceErrorの半分はこれが原因です
// 誤り
return "こんにちは、" + username;
// 正しい
return "こんにちは、" + userName;要件
- 関数名は
errorType、引数はmessageの 1 つ (文字列) - 戻り値は先頭の種類だけの文字列 (
ReferenceErrorSyntaxErrorTypeErrorなど) - 半角コロンより前の部分を切り出すこと
- コロンが含まれない文字列を渡された場合は、受け取った文字列をそのまま返すこと
入出力例
errorType("ReferenceError: userName is not defined") → "ReferenceError"
errorType("SyntaxError: Unexpected end of input") → "SyntaxError"
errorType("TypeError: Cannot read properties of undefined (reading 'title')") → "TypeError"
errorType("ReferenceError") → "ReferenceError"
errorType("") → ""