優れたコードとは、プログラムのエラーがプログラムをクラッシュさせないように先制的に防止し、代わりにエラーからの回復、ユーザーへの通知、エラーのログ記録などを行うことで、これらのエラーを適切に処理するコードです。 これはエラー処理と呼ばれ、JavaScriptでのエラー処理の主要なメカニズムはtry…catch構造です。

try…catchの使用方法を簡単に説明してから、try…catch…finallyおよびthrowステートメントを見て独自のカスタムエラーをスローします。

やってみて…キャッチ

try…catchの基本的な構文は次のとおりです。

try {
  // some code that my error-out
} catch (e) {
  // this will run only if the code in the try block errors-out
}

catchブロックがエラーオブジェクトにアクセスする方法に注意してください(e 上記の例では)。 エラーオブジェクトには、nameプロパティとmessageプロパティがあります。 ほとんどの環境では、エラーオブジェクトには stack プロパティもあり、スタックトレースによってエラーが発生します。

エラーオブジェクトをコンソールに記録すると、その名前とメッセージのプロパティが便利に連結されます

変数名のスペルを間違えた例を次に示します。

let myVariable = 2;
try {
  console.log(myVriable + 77);
} catch (e) {
  console.log('Oopsies -', e);
}

この場合、 catch ブロックが実行され、次のメッセージがコンソールに出力されます。

Oopsies - ReferenceError: myVriable is not defined

try…catchは実行時に発生したエラーのみを処理し、無効なJavaScriptは解析時にエラーアウトするため、プログラムはまったく実行されません。 代わりに、 ESLint のようなリンターを使用して、コードを作成するときにこれらのエラーを直接キャッチします。

カスタムエラーをスローする

多くの場合、純粋なJavaScriptエラーをキャッチする代わりに、エラーと見なされるべきプログラムで発生した条件をキャッチしたいと思うでしょう。 このために、throwステートメントを使用して、tryブロックに独自のエラーをスローし、エラーをキャッチして処理できるようにします。

let myVariable = prompt('Give me a number');

try {
  if (isNaN(+myVariable)) {
    // throws if the value provided can't be coerced to a number
    throw new Error('Not a number!');
  }
  console.log('Good choice', myVariable);
} catch (e) {
  console.log(e);
}

上記の例では、数値に強制できる値を入力しないと、カスタムエラーがスローされ、catch句によってキャッチされます。

また、エラーコンストラクターを使用して、最初の引数として渡されたカスタムメッセージを使用してエラーオブジェクトを作成していることもわかります。 この場合、エラーオブジェクトの名前は Error になりますが、特定のエラータイプを生成することもできます。

try {
  if (isNaN(+myVariable)) {
    throw new TypeError('Not a number!');
  }
  console.log('Good choice', myVariable);
} catch (e) {
  console.log(e);
}

エラーを再スローする

優れたコーディング手法は、予想されるエラーのみをキャッチして処理し、次に、潜在的な親のtry…catch構造によって処理される他のエラーを再スローすることです。

let myVariable = prompt('Give me a number');

try {
  if (isNaN(+myVariable)) {
    throw new TypeError('Not a number!');
  }
  console.log('Good choice', myVariable);
} catch (e) {
  if (e.name === 'TypeError') {
    console.log(e);
  } else {
    throw e;
  }
}

上記の例では、[X95X] TypeErrorとは異なるエラーがtry 句で発生した場合、 catch 句は、親を使用して処理されるエラーを再スローしますtry…catchコンストラクトを配置します。

試して…キャッチ…最後に

finally ブロックをタックオンして、 try のコードがエラーアウトをブロックするかどうかに関係なく、一部のコードが実行されるようにすることもできます。

let myVariable = 2;
try {
  console.log(myVriable + 77);
} catch (e) {
  console.log('Oopsies -', e);
} finally {
  console.log('Runs no matter what');
}

finally ブロックは、コードをクリーンアップするのに役立ちます。

試してみてください…最後に

finally と同様に、 catch 句はオプションであり、必要に応じてtry…finallyを使用して、エラーが発生したときに一部のコードが実行されるようにします。

ここでは、たとえば、存在しない要素に背景色を設定しようとします。 まず、try…catchを使用して…最後に:

try {
  document.querySelector('.not-there').style.backgroundColor = 'pink';
} catch (e) {
  console.log('Oh no -', e);
} finally {
  console.log('Finally runs');
}
console.log('After try block');

// Oh no - TypeError: Cannot read property 'style' of null
// Finally runs
// After try block

そして今、tryだけを使用しています…最後に:

try {
  document.querySelector('.here2').style.backgroundColor = 'pink';
} finally {
  console.log('Finally runs');
}
console.log('After try block');

// Finally runs
// Uncaught TypeError: Cannot read property 'style' of null

catch 句がない場合、エラーがキャッチされず、プログラムがクラッシュしますが、finally句のコードを実行した後であることに注意してください。