finally 在 JavaScript 中的真正作用

更新日期: 2025-09-19阅读: 95标签: 语法

很多开发者都知道 try...catch 语句,但对 finally 的使用却不那么熟悉。有时我们会觉得,写在 finally 里的代码和直接写在 try...catch 后面好像没什么区别。那么 finally 到底有什么特别的意义?它是不是多余的呢?


三种常见的代码写法

先看一个常见的场景:处理请求时的 loading 状态。不同开发者有不同的写法。

第一种写法,使用 finally:

let loading = false;

async function fetchData() {
  loading = true;
  try {
    await fetch('/api/data');
  } finally {
    loading = false;
  }
}

第二种写法,放在 try...catch 后面:

let loading = false;

async function fetchData() {
  loading = true;
  try {
    await fetch('/api/data');
  } catch (error) {
    // 处理错误
  }
  loading = false;
}

第三种写法,在 try 和 catch 中都写:

let loading = false;

async function fetchData() {
  loading = true;
  try {
    await fetch('/api/data');
    loading = false;
  } catch (error) {
    loading = false;
    // 处理错误
  }
}

从表面看,这三种写法都能正确重置 loading 状态。那么 finally 到底有什么特别之处?


finally 的独特之处

finally 的关键特点是:无论 try 中的代码是否抛出异常,无论是否有 return 语句,finally 中的代码一定会执行。

看这个例子:

function testFinally() {
  try {
    console.log('try 块执行');
    return 'try';
  } finally {
    console.log('finally 块执行');
  }
}

function testWithoutFinally() {
  try {
    console.log('try 块执行');
    return 'try';
  } catch (error) {
    // 错误处理
  }
  console.log('这行代码不会执行');
}

调用 testFinally() 时,虽然 try 块中有 return 语句,但 finally 中的代码仍然会执行。而 testWithoutFinally() 中,return 后面的代码永远不会执行。


实际应用中的重要性

在真实开发中,finally 的保证执行特性很重要。比如:

资源清理场景:

function processFile() {
  const fileHandle = openFile();
  try {
    // 处理文件
    processContent(fileHandle);
    return processResult; // 可能提前返回
  } catch (error) {
    console.error('处理失败:', error);
    throw error; // 重新抛出异常
  } finally {
    // 无论成功失败,都要关闭文件
    fileHandle.close();
  }
}

数据库连接场景:

async function queryDatabase() {
  const connection = await getConnection();
  try {
    const result = await connection.query('SELECT * FROM users');
    return result;
  } catch (error) {
    console.error('查询失败:', error);
    throw error;
  } finally {
    // 确保释放连接
    await connection.release();
  }
}

在这些场景中,如果没有 finally,很容易忘记释放资源,导致内存泄漏或资源耗尽。


特殊情况下的行为

finally 还有一些特殊行为需要注意:

function testReturn() {
  try {
    return 1;
  } finally {
    return 2; // 这个返回值会覆盖 try 中的返回值
  }
}

console.log(testReturn()); // 输出 2

如果 finally 中有 return 语句,它会覆盖 try 或 catch 中的返回值。同样,finally 中的 throw 语句也会覆盖之前的返回值或异常。


什么时候使用 finally

建议在以下情况使用 finally:

  1. 需要确保执行清理操作时(关闭文件、释放连接、重置状态)

  2. 代码中有多个 return 语句,但都需要执行某些收尾工作

  3. 希望代码意图更清晰,明确哪些是必须执行的操作


什么时候可以不用 finally

如果只是简单的代码流程,没有提前返回,也没有异常抛出的风险,那么把代码放在 try...catch 后面也是可以的。


总结

finally 不是 JavaScript 中多余的语法。它提供了重要的保证:某些代码一定会被执行。这个特性在资源管理、状态清理和错误处理中非常有用。

虽然在某些简单场景中,不用 finally 也能达到类似效果,但在复杂的业务逻辑中,finally 能提供更安全、更清晰的代码结构。

理解 finally 的真正作用,能帮助你写出更健壮、更可靠的 JavaScript 代码。它不是必须使用的,但确实是一个很有价值的工具

本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!

链接: https://fly63.com/article/detial/12924

30-seconds-code:总结了大量的使用ES6语法实现的代码块

30-seconds-code这个项目是一个非常优秀的JavaScript项目,这里总结了大量的使用ES6语法实现的代码块,项目的设计目标就是更简洁,更高效,更快速的实现基础代码模块。

如何让Node.js支持ES6的语法【转载】

不同版本的Node.js对Babel有不同的支持力度。为了让Node.js支持所需的ES6语法,可以加入Babel的支持。

JavaScript 语法流派现状调查

我们通常会有意无意的把JavaScript和其他编程语言区分开,有一个重要因素是……由于它的特性本身(太灵活了吧),它似乎不仅仅是一种语言,而更像是一帮老司机在矫情造作之下乱伦出来的生态系统。

js基本语法

JavaScript是一种轻量性脚本语言 ,其语句以;结束,语句块用{...},js应许末尾不加,浏览器Js引擎会自动在每个语句的结尾补上,js功能主要是:动态修改html页面内容,包括创建、删除html页面元素、修改html页面元素的内容

带@的css语法,你知道多少?

css的顶层样式表由两种规则组成的规则列表构成,一种称为at—rule规则,也就是at规则,另一种是qualified rule,也就是普通规则。今天就学习一下at规则

es6 Module语法

export用于定义要输出的变量(let、var、const、function、class),定义的变量与值是动态绑定关系。匿名定义本质上是采用 default 为名称,与上面2个的区别是在加载时可以不用写大括号还能自定义名称。

es6中的语法_面试es6常用语法整理

箭头函数;扩展运算符 ...的一个通用的用法就是把对象展开;变量声明es6中不建议继续使用var来声明变量,推荐使用let和const声明,以此避免var声明存在的弊端

常见的JavaScript“陷阱”

随着ES6标准的普及,JavaScript已经拥有许多新的语法糖,这让我们编写可读的,高质量的代码变得更加方便,但即使这样仍然会遇到一些潜在的陷阱。

.htaccess文件RewriteRule语法规则

.htaccess文件是运行Apache Web Server的Web服务器的配置文件,对配置和重定向Apache Web Server文件系统很有用。在这里,我将讨论.htaccess文件RewriteRule语法规则。

什么是抽象语法树?「译」

AST 是抽象语法树的缩写词,表示编程语言的语句和表达式中生成的 token。有了 AST,解释器或编译器就可以生成机器码或者对一条指令求值。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!