HOWTO · JavaScript
JavaScript 中的嵌套函数
本教程演示 JavaScript 中的嵌套函数。
本页内容
嵌套函数是在另一个函数内部定义的函数。外层函数决定内层函数在哪些位置可用,而内层函数可以读取其定义所在作用域中的变量。本指南将介绍如何定义和调用嵌套函数、访问外层变量有何用处,以及如何让这种写法保持清晰易读。
什么是嵌套函数?
在 JavaScript 中,内层函数可以使用外层函数的参数和局部变量。如果外层函数返回后,内层函数仍然可以访问,那么它就能继续访问自己引用的变量。函数及其保留的词法访问权限构成了闭包。
运行以下示例:
function makeAdder(amount) {
return function add(value) {
return amount + value;
};
}
const addFive = makeAdder(5);
console.log(addFive(10));
15
提供的运行结果是 15。makeAdder(5) 返回内层函数,随后用参数 10 调用该函数;内层函数会从外层调用的词法作用域中读取 amount。返回内层函数是一种常见的闭包用法,但这不一定属于柯里化:柯里化特指将一个接受多个参数的函数转换为一系列每次接受一个参数的函数。
使用嵌套函数的优点
将辅助函数嵌套起来,可以让它靠近使用它的代码,也不必在外层作用域中增加名称。返回的内层函数还可以在多次调用之间保留私有状态。例如,计数器工厂可以创建局部变量 count,并返回一个用于更新它的函数。每次调用工厂都会创建各自的绑定,因此不同计数器可以维护独立状态。闭包可以实现这种行为,但并不保证执行速度更快。
内层函数能够访问外层变量,但这不代表所有回调函数都是嵌套函数。在其他位置定义后再传入函数的回调,是传递给高阶函数的回调;只有当它在另一个函数内部定义时,才是嵌套函数。
何时使用嵌套函数
当函数需要使用外层函数的值或作用域、辅助函数只在外层函数中有意义,或你想创建一个由某个值(例如乘数)配置的函数时,可以使用嵌套函数。返回这个配置好的函数后,调用方就能重复使用该设置,而不必每次调用都再次传入。
如果辅助函数不需要外层函数的变量或作用域,将它定义在更外层的位置,可能更便于复用和测试。应在嵌套关系清晰或需要保留状态时采用这种写法,而不是仅仅因为函数可以定义在另一个函数里面。
嵌套函数的最佳实践
让每个函数各司其职,并使用能说明外层准备工作与内层操作之间关系的名称。避免增加过多嵌套层级,以免控制流程难以理解;如果某个辅助函数可以独立存在,或外层函数变得难以快速读懂,就将它提取出来。
只要闭包仍可访问,它就会保留对其词法环境的访问权限。这是正常行为,并不意味着应一概避免使用闭包。在长期运行的代码中,如果闭包还会让大型对象保持可访问状态,就应避免让它的可访问时间超过实际需要。
总结
嵌套函数定义在另一个函数内部,并可通过词法作用域使用外层函数的变量。将它返回后,它可以作为闭包保留对这些变量的访问,从而实现私有状态和可复用的配置。当这种关系能让代码更清楚时,就可以采用嵌套函数;如果嵌套让逻辑更难理解,就应减少嵌套。
常见问题
- JavaScript 中的嵌套函数是什么? 嵌套函数是在另一个函数内部定义的函数,可以访问外层词法作用域中的变量。
- 为什么使用嵌套函数? 它可以将辅助函数限制在局部作用域、通过闭包保留状态,或创建由外层值配置的函数。嵌套函数本身不会带来性能提升。
- 嵌套函数可以访问外层函数的变量吗? 可以。内层函数能读取其词法作用域中的变量;如果外层函数返回后内层函数仍可访问,它也能继续读取这些变量。
- 嵌套函数有什么缺点? 嵌套过多会让代码更难阅读和维护。
- 怎样才能更好地使用嵌套函数? 保持函数职责单一、使用清晰的名称;如果辅助函数不需要外层作用域,就在更外层定义它。