天天看點

js深度了解下try...catch...finally

目錄

1. 文法

2. 詳解

3. 無條件的catch塊

4. finally塊

5. 嵌套try

1. 文法

try {
   try_statements
}
[catch (exception_var_1 if condition_1) { // non-standard
   catch_statements_1
}]
...
[catch (exception_var_2) {
   catch_statements_2
}]
[finally {
   finally_statements
}]
      

try_statements

需要被執行的語句。

catch_statements_1

catch_statements_2

如果在

try

塊裡有異常被抛出時執行的語句。

exception_var_1

exception_var_2

用于儲存關聯

catch

子句的異常對象的辨別符。

condition_1

一個條件表達式。

finally_statements

try

語句塊之後執行的語句塊。無論是否有異常抛出或捕獲這些語句都将執行。

2. 詳解

try

語句包含了由一個或者多個語句組成的

try

塊, 和至少一個

catch

塊或者一個

finally

塊的其中一個,或者兩個兼有, 下面是三種形式的

try

聲明:

  1. try...catch

  2. try...finally

  3. try...catch...finally

catch

子句包含

try

塊中抛出異常時要執行的語句。也就是,你想讓

try

語句中的内容成功, 如果沒成功,你想控制接下來發生的事情,這時你可以在

catch

語句中實作。 如果在

try

塊中有任何一個語句(或者從

try

塊中調用的函數)抛出異常,控制立即轉向

catch

子句。如果在

try

塊中沒有異常抛出,會跳過

catch

子句。

finally

子句在

try

塊和

catch

塊之後執行但是在下一個

try

聲明之前執行。無論是否有異常抛出或捕獲它總是執行。

你可以嵌套一個或者更多的

try

語句。如果内部的

try

語句沒有

catch

子句,那麼将會進入包裹它的

try

語句的

catch

子句。

3. 無條件的

catch

所謂無條件catch塊就是單個子句的try..catch 抛出的異常都會被catch捕獲,例如,當在下面的代碼中發生異常時,控制轉移到

catch

子句。

try {
  nonExistentFunction();  // 不存在的函數
} catch (error) {
  console.error(error);
  // 控制台列印: ReferenceError: nonExistentFunction is not defined
  // 被catch捕獲錯誤。
}
           

列印出來的錯誤時可以自定義的。

catch

塊指定一個辨別符,該辨別符儲存由

throw

語句指定的值。

catch

塊是唯一的,因為當輸入

catch

塊時,JavaScript 會建立此辨別符,并将其添加到目前作用域;辨別符僅在

catch

塊執行時存在;

catch

塊執行完成後,辨別符不再可用。

try {
   throw "自定義一些文字錯誤"; // generates an exception
}
catch (e) {
   console.log(e); // 控制台列印:自定義一些文字錯誤
}
           
try {
   throw  {name: '張三'}; // 自定義
}
catch (e) {
   
   console.log(e); // 列印:  {name: '張三'}
}
           

try

塊中的抛出一個異常時, 

exception_var

(如

catch (e)

中的

e

)用來儲存被抛出聲明指定的值。你可以用這個辨別符來擷取關于被抛出異常的資訊。

這個辨別符是

catch

子語句内部的。換言之,當進入

catch

子語句時辨別符建立,

catch

子語句執行完畢後,這個辨別符将不再可用。

4. 

finally

finally

塊包含的語句在

try

塊和

catch

之後,

try..catch..finally

塊後的語句之前執行。請注意,無論是否抛出異常

finally

子句都會執行。此外,如果抛出異常,即使沒有

catch

子句處理異常,

finally

子句中的語句也會執行。

openMyFile()
try {
   // tie up a resource
   writeMyFile(theData);
}
finally {
   closeMyFile(); // always close the resource
}
           

5. 嵌套try

例子1: 

try {
  try {
    throw new Error("oops"); // 抛出oops錯誤對象
  }
  finally {
    console.log("finally");  // 必須執行的
  }
}
catch (ex) {
  console.error("outer", ex.message);
}

// 結果:
// "finally"
// "outer" "oops"
           

例2  如果我們已經在 try 語句中,通過增加一個 catch 語句塊捕獲了異常

try {
  try {
    throw new Error("oops");  // 抛出異常
  }
  catch (ex) {
    console.error("inner", ex.message);  // 被捕獲到了
  }
  finally {
    console.log("finally");  // 怎麼樣都會執行
  }
}
catch (ex) {
  console.error("outer", ex.message);  // 屬于這個try catch 沒有異常抛出
}

// 結果:
// "inner" "oops"
// "finally"
           

例3 在新增的catch裡不幹正事繼續抛錯誤

try {
  try {
    throw new Error("oops");  // 異常
  }
  catch (ex) {
    console.error("inner", ex.message);  // 捕獲到異常
    throw ex;     //  不幹正事的抛出異常 但是還是會先執行finally内的内容
  }
  finally {
    console.log("finally");  // try 和 catch 執行完就執行。不管别人
  }
}
catch (ex) {
  console.error("outer", ex.message); // 捕獲到屬于這個try -catch 的異常
}

// 結果:
// "inner" "oops"
// "finally"
// "outer" "oops"
           

例4 特别!!!

function setName () {
  try {
    try {
      throw new Error("oops");
    }
    catch (ex) {
      console.error("inner", ex.message);
      throw ex;
    }
    finally {
      console.log("finally");
      return;
    }
  }
  catch (ex) {
    console.error("outer", ex.message);  
  }
  
  // 注: 此 try catch 語句需要在 function 中運作才能作為函數的傳回值, 否則直接運作會報文法錯誤
  // 結果:
  // "inner" "oops"
  // "finally"
}
           
如果從

finally

塊中傳回一個值,那麼這個值将會成為整個

try-catch-finally

的傳回值,無論是否有

return

語句在

try

catch

中。這包括在

catch

塊裡抛出的異常。因為 finally 塊裡的 return 語句,"oops" 沒有抛出到外層,從 catch 塊傳回的值同樣适用。

繼續閱讀