你不知道的 JavaScript 系列中( 33 ) - try...finally 和 switch 要注意的地方

try..finally
try..finally 中finally 中的代碼總是會在 try 之後執行,如果有 catch 的話則在 catch 之後執行。也可以將 finally 中的代碼看作一個回調函數,即無論出現什麼情況最後一定會被調用
得到返回值的代碼是在 finally 之前還是之後執行呢?
function foo() {
  try {
    return 42;
  }
  finally {
    console.log( "Hello" );
  }
  console.log( "never runs" );
}
console.log( foo() );
// Hello
// 42

這裏 return 42 先執行,並將 foo() 函數的返回值設置爲 42。然後 try 執行完畢,接着執行 finally。最後 foo() 函數執行完畢,console.log(..) 顯示返回值

 

try 中的 throw 也是如此:
function foo() {
  try {
    throw 42;
  }
  finally {
    console.log( "Hello" );
  }
  console.log( "never runs" );
}
console.log( foo() );
// Hello
// Uncaught Exception: 42

 

如果 finally 中拋出異常(無論是有意還是無意),函數就會在此處終止。如果此前 try 中 已經有 return 設置了返回值,則該值會被丟棄:
function foo() {
  try {
    return 42;
  }
  finally {
    throw "Oops!";
  }
  console.log( "never runs" );
}
console.log( foo() ); // Uncaught Exception: Oops!

 

finally 中的 return 會覆蓋 try 和 catch 中 return 的返回值:

function foo() {
  try {
    return 42;
  }
  finally {
    // 沒有返回語句,所以沒有覆蓋
  }
}

function bar() {
  try {
    return 42;
  }
  finally {
    // 覆蓋前面的 return 42
    return;
  }
}

function baz() {
  try {
    return 42;
  }
  finally {
    // 覆蓋前面的 return 42 return "Hello";
  }
}

foo(); // 42
bar(); // undefined
baz(); // Hello

通常來說,在函數中省略 return 的結果和 return; 及 return undefined; 在 finally 中省略 return 則會返回前面的 return 設定的返回值。



switch

switch 中時可能會需要通過強制類型轉換來進行相等比較,這時就需要做一些特殊處理:
var a = "42";
switch (true) {
  case a == 10:
    console.log( "10 or '10'" );
    break;
  case a == 42;
    console.log( "42 or '42'" );
  break;
  default:
  // 永遠執行不到這裏
}
// 42 or '42'

除簡單值以外,case 中還可以出現各種表達式,它會將表達式的結果值和 true 進行比較。 因爲a == 42的結果爲true,所以條件成立。

在這裏使用 || 和 && 等邏輯運算符就很容易掉進坑裏:

var a = "hello world";
var b = 10;
switch (true) {
  case (a || b == 10):
    // 永遠執行不到這裏
    break;
  default:
    console.log( "Oops" );
}
// Oops

因爲(a || b == 10)的結果是"hello world"而非true,所以嚴格相等比較不成立

var a = 10;
switch (a) {
  case 1:
  case 2:
    // 永遠執行不到這裏
  default:
    console.log( "default" );
  case 3:
    console.log( "3" );
    break;
  case 4:
    console.log( "4" );
}
// default
// 3

上例中的代碼是這樣執行的,首先遍歷並找到所有匹配的 case,如果沒有匹配則執行default 中的代碼。因爲其中沒有 break,所以繼續執行已經遍歷過的 case 3 代碼塊,直 到 break 爲止

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章