finally 中的代码总会在 try 之后执行,如果有 catch 的话则在 catch 之后执行。可以将 finally 中的代码看作一个回调函数,即无论出现什么情况最后一定会被调用。
    如果 try 中有 return 语句会出现什么情况呢?

    1. function foo() {
    2. try {
    3. return 42;
    4. }
    5. finally {
    6. console.log( "Hello" );
    7. }
    8. console.log( "never runs" );
    9. }
    10. console.log( foo() );
    11. // Hello
    12. // 42

    这里return 42先执行,并将foo()函数的返回值设置为42。然后try执行完毕,接着执行 finally。最后 foo() 函数执行完毕,console.log(..) 显示返回值。
    try 中的 throw 也是如此:

    1. function foo() {
    2. try {
    3. throw 42;
    4. }
    5. finally {
    6. console.log( "Hello" );
    7. }
    8. console.log( "never runs" );
    9. }
    10. console.log( foo() );
    11. // Hello
    12. // Uncaught Exception: 42

    如果 finally 中抛出异常(无论是有意还是无意),函数就会在此处终止。如果此前 try 中已经有 return 设置了返回值,则该值会被丢弃:

    1. function foo() {
    2. try {
    3. return 42;
    4. }
    5. finally {
    6. throw "Oops!";
    7. console.log( "never runs" );
    8. }
    9. }
    10. console.log( foo() );
    11. // Uncaught Exception: Oops!

    continuebreak 等控制语句也是如此:

    1. for (var i=0; i<10; i++) {
    2. try {
    3. continue;
    4. }
    5. finally {
    6. console.log( i );
    7. }
    8. }
    9. // 0 1 2 3 4 5 6 7 8 9

    continue 在每次循环之后,会在 i++ 执行之前执行 console.log(i),所以结果是 0..9 而非1..10
    ES6 中新加入了 **yield**,可以将其视为 **return** 的中间版本。然而与 **return** 不同的是,**yield****generator**(ES6 的另 一个新特性)重新开始时才结束,这意味着**try { .. yield .. }**并未结束, 因此 **finally** 不会在 **yield** 之后立即执行。
    finally 中的 return 会覆盖 trycatchreturn 的返回值:

    1. function foo() {
    2. try {
    3. return 42;
    4. }
    5. finally {
    6. // 没有返回语句,所以没有覆盖
    7. }
    8. }
    9. console.log(foo())
    10. // 42
    1. function bar() {
    2. try {
    3. return 42;
    4. }
    5. finally {
    6. // 覆盖前面的 return 42
    7. return;
    8. }
    9. }
    10. console.log(bar())
    11. // undefined
    1. function baz() {
    2. try {
    3. return 42;
    4. }
    5. finally {
    6. // 覆盖前面的 return 42
    7. return "Hello";
    8. }
    9. }
    10. console.log(baz())
    11. // Hello

    通常来说,在函数中省略return的结果和return;return undefined;是一样的,但是在 finally 中省略 return 则会返回前面的 return 设定的返回值。
    还可以将 finally 和带标签的 break 混合使用

    1. function foo() {
    2. bar: {
    3. try {
    4. return 42;
    5. }
    6. finally {
    7. // 跳出标签为bar的代码块
    8. break bar;
    9. }
    10. }
    11. console.log( "Crazy" );
    12. return "Hello";
    13. }
    14. console.log( foo() );
    15. // Crazy
    16. // Hello

    切勿这样操作。利用 finally 加带标签的 break 来跳过 return 只会让代码变得晦涩难懂。