2

This question may appear similar to others that have been answered, but I can't find an answer relating to JavaScript.

What is the difference between code in a finally block and code that comes after the entire try ... catch ... finally statement?

That is, what is the difference between this code:

try {
  f(x);
}
catch(e) {
  g(e);
}
finally {
  h(y);
}

and this code:

try {
  f(x);
}
catch(e) {
  g(e);
}
h(y);
Ben Zelnick
  • 433
  • 4
  • 14
  • `finally` only makes a difference when using `return` or another `throw`. See [the spec](//tc39.es/ecma262/#sec-try-statement-runtime-semantics-evaluation) and [the docs](//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch#description). – Sebastian Simon Jun 27 '21 at 01:22
  • 1
    [Duplicate](//google.com/search?q=site%3Astackoverflow.com+js+why+use+finally) of [Uses of the finally statement](/q/18251156/4642212). – Sebastian Simon Jun 27 '21 at 01:24
  • Are you referring to the answer that @CertainPerformance gave? – Ben Zelnick Jun 27 '21 at 01:25
  • _“Are you referring to the answer that @CertainPerformance gave?”_ — I’m not sure what you mean… Both my comments refer to your question. – Sebastian Simon Jun 27 '21 at 01:27
  • Sorry—I meant to ask if you were making the same point that @CertainPerformance made in his answer. – Ben Zelnick Jun 27 '21 at 01:30
  • Probably. What `finally` is used for is well documented. – Sebastian Simon Jun 27 '21 at 01:34

2 Answers2

3

One difference is that, if a value is returned in a finally, it will override values returned from inside the prior try and catch blocks:

function foo() {
  try {
    throw new Error('1');
  } catch(e) {
    return '2';
  } finally {
    return '3';
  }
}
console.log(foo());

Returning from a finally will also prevent throws in a try or catch from percolating outward - instead, only the finally's normal return completion value will be the result.

(function() {
  try {
    try {
      throw new Error('oops');
    } catch (ex) {
      console.error('inner', ex.message);
      throw ex;
    } finally {
      console.log('finally');
      return;
    }
  } catch (ex) {
    // not entered into
    console.error('outer', ex.message);
  }
})();
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • And, according to the duplicate question suggested by @SebastianSimon, any *other* code (not just `return` statements) in the finally block will run even if there is an error thrown or `return` in the `catch` block. – Ben Zelnick Jun 27 '21 at 01:29
  • "will also result in throws in a try or catch from percolating outward"—do you mean that it will *prevent* them from percolating outward? – Ben Zelnick Jun 27 '21 at 01:36
1

I'll admit this question had me scratching my head at first. But a look at the MDN reference for try...catch includes this salient section on "Returning from a finally-block". It appears that if you return from a finally block, it will override anything returned or thrown from the preceding try or catch blocks. So while your example may be identical, if you were to change it to this:

try {
  return f(x);
}
catch(e) {
  throw g(e);
}
finally {
  return h(y);
}

...it would fundamentally differ from this:


try {
  return f(x);
}
catch(e) {
  throw g(e);
}
return h(y);
Alexander Nied
  • 12,804
  • 4
  • 25
  • 45