你不知道的 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 为止

posted @ 2020-12-03 08:42  wzndkj  阅读(505)  评论(0编辑  收藏  举报