JavaScript Object Oriented Programming: Exceptions

JavaScript

「例外(Exceptions)」是一個特別且重要的處理錯誤的方法。

Check-first error handling

假設我們要執行 func 這個 method,首先會檢查這個 method 是否存在。

if (window.func) {
  func();
}

但檢查了是否存在,不代表型別正確,因此我們必須再檢查這個 method 的型別是否為 function。

if (typeof func == 'function') {
  func();
}

但意外或錯誤是永遠檢查不完的,例如,這個 method 的內部可能有些問題。因此,我們可以改用「Try..Catch」來處理。

The try..catch construct

上一個例子是預先把可能發生的問題都檢查一次,例如:存在與否、型別是否正確,如果通過檢查再執行。而「Try..Catch」從另外一個角度來處理 - 先執行,如果有錯再處理。範例如下。

try {
  func();
} catch (e) {
  alert(e);
}

這個「e」會告訴我們到底發生什麼問題。

try {
  var a = 5,
    res = func(a);

  if (res > 0) {
    doA();
  } else {
    doB();
  }
} catch (e) {
  console.log('name: ' + e.name); //name: ReferenceError
  console.log('message: ' + e.message); //message: doB is not defined
}

由錯誤訊息可知,doB 這個 function 沒有被定義,因此無法執行而出錯。

The full form of try..catch..finally

try {
  //try statemenets ..
} catch (exception) {
  //catch statements ..
} finally {
  //finally statements ..
}

首先執行 try 區塊內的程式碼,如果沒有出錯,則 catch 區塊會被忽略不執行。如果有錯誤產生,則 exception 會被設定值,catch 區塊會被執行。無論如何,最後,finally 區塊都會被執行。

try..catch..finally and return

在 try 區塊執行 return statments,控制權會在執行完 finally 區塊後才交回給原呼叫的 function。所以如下程式碼所示,會先 alert 「done」,再 alert 「2」。

function inc(a) {
  try {
    return a + 1;
  } catch (e) {
    //catch statements...
  } finally {
    alert('done'); // 1. alert "done"
  }
}
alert(inc(1)); // 2. alert "2"

The throw statement

基本上,錯誤可以分為兩種:「Programmatic errors」和「Execution flow errors」。

因此,使用 try…catch 與 throw 於 Execution flow errors 是一個不錯的選擇,範例如下。

try {
  throw 5;
} catch (e) {
  alert('Caught: ' + e);
}

A validator example

假設我們需要一個年齡的驗證工具,幫助我們檢查使用者輸入的年齡是否合法。如果沒有輸入任何東西,則跳出;如果輸入非文字,則丟出錯誤;如果是數字,則顯示可接受的訊息。

function validatorAge(age) {
  if (age === '') {
    return; // no age to valid
  }
  age = +age;

  if (isNaN(age)) {
    throw {
      name: 'BadAge',
      message: 'Age out of range',
    };
  }
}

try {
  var age = prompt('Enter your age');
  validatorAge(age);
  alert('The age is accepted');
} catch (e) {
  alert('Error: ' + e.message);
}

Changes in the usage pattern

除了 try…catch 的用法,當然我們也可以使用 error-checking 的方法。

function validatorAge(age) {
  if (age === '') {
    return; // no age to valid
  }
  age = +age;

  if (isNaN(age)) {
    return false;
  } else {
    return true;
  }
}

var value = prompt('Enter your age'),
  error = validatorAge(value);

if (!error) {
  // process error
  alert('Invalid error!');
} else {
  // success
  alert('The age is accepted');
}

Comparison

Exception analysis and rethrow

有時候,程式碼可能會產生不同種類的錯誤。因此,我們使用「if」來選擇適當的動作。結構類似如下:

try {
  // 1. do smth
} catch (e) {
  if (e instanceof ValidationError) {
    // 2.1 process e
  } else if (e instanceof PermissionError) {
    // 2.2 process e
  } else {
    // 3. we don't know how to deal with e
    throw e;
  }
}

在 try 區塊可能丟出了某些錯誤,有些錯誤是我們已知的,例如:ValidationError 和 PermissionError,然後去處理這些已知的 e。但有些我們並不確定,因此直接丟出 e。這裡丟出的 e,需要由外層的 try..catch 來處理。

Summary

Reference


這篇文章的原始位置在這裡-JavaScript Object Oriented Programming - Exceptions

由於部落格搬遷至此,因此在這裡放了一份,以便閱讀;部份文章片段也做了些許修改,以期提供更好的內容。

ReferenceError NaN javascript