Back

JavaScript エラーの種類とメッセージを理解する

JavaScript エラーの種類とメッセージを理解する

すべての JavaScript 開発者は、コンソールに表示される赤いエラーメッセージを見つめ、何が間違っているのか疑問に思った経験があるでしょう。これらのエラータイプを理解することは、単に壊れたコードを修正することだけではありません。より信頼性の高いアプリケーションを作成し、問題をより迅速にデバッグすることが目的です。各エラーが何を意味し、なぜ発生するのかを理解すると、リアクティブなデバッグからプロアクティブなエラー防止へと変革できます。

重要なポイント

  • JavaScript エラーは、コードの問題に関する具体的なフィードバックを提供する namemessage プロパティを持つ構造化されたオブジェクトです
  • 8つのネイティブエラータイプが存在します:SyntaxError、ReferenceError、TypeError、RangeError、URIError、EvalError、AggregateError、InternalError
  • try-catch ブロックとカスタムエラークラスを使用した適切な例外処理により、アプリケーションの信頼性が向上します
  • グローバルエラーハンドラとブラウザのデバッグツールは、本番環境でのエラー追跡に不可欠です

JavaScript エラーとは?

JavaScript エラーは、コード実行中の問題を表すオブジェクトです。各エラーには、そのタイプを識別する name プロパティと、何が問題だったかを説明する message プロパティが含まれています。これらはランダムな障害ではなく、コード内の特定の問題に関する構造化されたフィードバックです。

8つのネイティブエラータイプ

SyntaxError:ルール違反

SyntaxError は、無効な構文のために JavaScript がコードを解析できない場合に発生します。インタープリターは実行が始まる前に停止します。

// Missing closing parenthesis
console.log("Hello World");
// SyntaxError: missing ) after argument list

// Invalid JSON parsing
JSON.parse("{'invalid': 'json'}");
// SyntaxError: Unexpected token ' in JSON at position 1

一般的な原因には、括弧の欠落、閉じられていない文字列、または不正な形式の JSON が含まれます。これらのエラーは、コードが全く実行されないようにします。

ReferenceError:未定義の使用

ReferenceError は、現在のスコープに存在しない変数にアクセスしようとしたときに発生します。

console.log(userName);
// ReferenceError: userName is not defined

function greet() {
  let message = "Hello";
}
greet();
console.log(message);
// ReferenceError: message is not defined

これは通常、タイプミス、宣言前の変数へのアクセス、またはスコープの混乱から生じます。

TypeError:型の不一致操作

TypeError は、互換性のない型に対して操作を実行したときに発生します。例えば、関数でないものを呼び出したり、null または undefined のプロパティにアクセスしたりする場合です。

const num = 42;
num();
// TypeError: num is not a function

const user = null;
console.log(user.name);
// TypeError: Cannot read properties of null (reading 'name')

これらは JavaScript アプリケーションで最も一般的なランタイムエラーの1つです。

RangeError:範囲外

RangeError は、値が許可された範囲を超えていることを示します。

const arr = new Array(-1);
// RangeError: Invalid array length

const num = 1;
num.toPrecision(101);
// RangeError: toPrecision() argument must be between 1 and 100

配列コンストラクタ、数値メソッド、またはコールスタックを超える再帰関数を扱う際には注意が必要です。

URIError:不正な形式の URI

URIError は、URI エンコードまたはデコード関数が無効なパラメータを受け取ったときに表示されます。

decodeURIComponent('%');
// URIError: URI malformed

encodeURI('\uD800');
// URIError: URI malformed

これらのエラーは、特殊文字や不完全なパーセントエンコーディングを含む URL を処理する際に発生します。

EvalError:eval() の問題

EvalError は仕様には存在しますが、現代の JavaScript ではスローされません。下位互換性のために残されています。eval() に関する歴史的な問題がこのエラータイプをトリガーしていました。

AggregateError:複数の失敗

AggregateError は、複数のエラーを1つのオブジェクトにラップします。特に Promise.any() で有用です。

Promise.any([
  Promise.reject(new Error("First failure")),
  Promise.reject(new Error("Second failure"))
]).catch(err => {
  console.log(err instanceof AggregateError); // true
  console.log(err.errors); // Array of individual errors
});

InternalError:エンジンの制限

InternalError(非標準、Firefox 固有)は、JavaScript エンジンが内部制限に達したときに発生します。

function recursiveFunction() {
  recursiveFunction();
}
recursiveFunction();
// InternalError: too much recursion (Firefox)
// RangeError: Maximum call stack size exceeded (Chrome)

try…catch による例外処理

JavaScript は、trycatchfinallythrow ステートメントを通じて構造化された例外処理を提供します。

try {
  // Code that might throw an error
  const data = JSON.parse(userInput);
  processData(data);
} catch (error) {
  if (error instanceof SyntaxError) {
    console.error("Invalid JSON format:", error.message);
  } else if (error instanceof TypeError) {
    console.error("Data processing error:", error.message);
  } else {
    // Re-throw unknown errors
    throw error;
  }
} finally {
  // Cleanup code runs regardless
  closeConnections();
}

throw ステートメントはカスタムエラーを作成します:

function validateAge(age) {
  if (age < 0) {
    throw new RangeError("Age cannot be negative");
  }
  if (typeof age !== 'number') {
    throw new TypeError("Age must be a number");
  }
  return age;
}

エラー処理のベストプラクティス

具体的なエラータイプを使用する カスタムエラーをスローする際には、汎用的な Error オブジェクトではなく、型の問題には TypeError、境界違反には RangeError をスローします。

適切なレベルでエラーを処理する すべての関数を try-catch でラップしないでください。意味のある対応ができる場所でエラーを処理します。

エラーコンテキストを保持する 再スロー時:

try {
  riskyOperation();
} catch (error) {
  // Add context without losing original stack trace
  error.message = `Failed during user ${userId} operation: ${error.message}`;
  throw error;
}

カスタムエラークラスを作成する ドメイン固有の問題に対して:

class ValidationError extends Error {
  constructor(field, value) {
    super(`Invalid value for ${field}: ${value}`);
    this.name = 'ValidationError';
    this.field = field;
    this.value = value;
  }
}

JavaScript エラーの効果的なデバッグ

現代のブラウザは優れたデバッグツールを提供しています。スタックトレースは、エラーに至る実行パスを示します。ブレークポイントを使用して、エラーが発生する前に実行を一時停止します。コンソールのエラーメッセージには、多くの場合、正確な行番号とファイルが含まれています。

本番アプリケーションの場合、グローバルエラーハンドラを実装します:

window.addEventListener('error', (event) => {
  console.error('Global error:', event.error);
  // Send to error tracking service
});

window.addEventListener('unhandledrejection', (event) => {
  console.error('Unhandled promise rejection:', event.reason);
});

まとめ

JavaScript のエラータイプを理解することで、デバッグが推測から体系的な問題解決へと変わります。SyntaxError から AggregateError まで、各エラータイプは何が間違っていて、どこを見るべきかを正確に教えてくれます。try-catch ブロックを使用した適切な例外処理と意味のあるエラーメッセージを組み合わせることで、優雅に失敗し、問題が発生したときに明確なフィードバックを提供するアプリケーションを構築できます。重要なのは、すべてのエラーを回避することではなく、エラーが発生したときにインテリジェントに処理することです。

よくある質問

エラーをスローすると、実行が即座に停止し、try-catch ブロックでキャッチされるか、プログラムがクラッシュするまでバブルアップします。エラー値を返すと実行は継続しますが、明示的なチェックが必要です。通常のフローを中断すべき例外的なケースには throw を使用し、予想される失敗には戻り値を使用します。

Promise のリジェクションをグローバルにキャッチするには、unhandledrejection イベントで window.addEventListener を使用します。非同期関数の場合は、try-catch ブロックでラップするか、返された Promise に catch ハンドラをアタッチします。これにより、サイレント失敗を防ぎ、本番環境でのエラー追跡に役立ちます。

各 JavaScript エンジンは、エラータイプに関する同じ ECMAScript 仕様に従いながら、エラーメッセージを異なる方法で実装しています。Chrome の V8、Firefox の SpiderMonkey、Safari の JavaScriptCore は、メッセージの表現が独自である可能性がありますが、エラータイプと動作は一貫しています。

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay