在JS函数中"最后 "的返回值获胜的实例

72 阅读2分钟

在JavaScript函数中,哪个return

function test() {
  return 'one';
  return 'two';
  return 'three';
}

你可能会说,"嗯,是第一个",但我要尝试说服你是最后一个

别担心,上面的函数肯定会返回'one' ,但在这种情况下,第一个返回语句会阻止其他语句的执行。最后一个返回值是return 'one' ,这才是赢家。当然,这也是第一个返回,但我仍然是对的。[折叠手臂,看起来很得意]

我知道你在想什么,你在想 "闭嘴,Jake",但请忍耐一下......

最后

finally 是一个东西:

function finallyTest() {
  try {
    console.log('one');
    return 'three';
  } catch (err) {
    console.log('error');
  } finally {
    console.log('two');
  }
}

console.log(finallyTest());
console.log('four');

上面的日志'one','two','three','four'finally 块总是在try/catch 之后运行,即使trycatch 返回。

直到最近,我发现自己在异步函数中像这样使用finally ,我才在JavaScript中使用了很多:

async function someAsyncThing() {
  startSpinner();

  try {
    await asyncWork();
  } catch (err) {
    if (err.name === 'AbortError') return;
    showErrorUI();
  } finally {
    stopSpinner();
  }
}

总之,关于finally ,令人兴奋的是它让我们有机会从一个函数调用中多次返回

function manyHappyReturns() {
  try {
    return 'one';
  } finally {
    try {
      return 'two';
    } finally {
      return 'three';
    }
  }
}

...而调用manyHappyReturns() 的结果是'three'

最后的返回总是赢的。不是在函数中最后出现的,不,那会很疯狂,而是最后执行的。最后一个返回获胜的方式与最后一个变量赋值获胜的方式相同;我们不计算那些没有发生的变量赋值。事实上,它的规格很像一个赋值。return 为函数分配了一个结论,所以一个return 覆盖了之前的return 。同样的情况也发生在Java和Python中。感谢Daniel Ehrenberg让我意识到了这个小怪癖!

作为一个副作用,从finally 返回会清除一个抛出的错误:

function catchThis() {
  try {
    throw Error('boom');
  } finally {
    return 'phew';
  }
}

调用catchThis() 的结果是'phew'

这有什么实际应用吗?

没有。谢谢你的阅读!请不要在求职面试时问别人这个问题。

奖励:承诺

异步函数的行为与上述相同(除了返回一个承诺)。然而,promise.finally() 的行为是不同的:

const promise = Promise.resolve('one').finally(() => 'two');

在这里,promise'one' 一起完成。这可能是因为承诺反应是回调,而回调的调用者(在这种情况下就是承诺)没有办法分辨运行return undefined 的函数和根本不运行return 的函数之间的区别。由于它不能模仿上面的finally 的边缘情况,所以它只是忽略了它。

虽然,promise.finally 确实会影响承诺的解决时间

const wait = (ms) => new Promise((r) => setTimeout(() => r(), ms));

const promise = Promise.resolve('one').finally(async () => {
  await wait(2000);
  return 'two';
});

在这种情况下,promise 仍然与'one' 一起实现,但需要两秒钟才能完成。