JavaScript 函数是可重复执行的代码块,用来封装逻辑、接收输入(参数)、处理数据并返回结果。函数的作用域决定变量能被访问的范围,而闭包是函数与其词法环境的组合,让内部函数即使在外部函数执行完毕后,仍能访问其变量。
函数的基本写法和调用
可以用函数声明或函数表达式定义:
- 函数声明:function sayHello(name) { return `Hello, ${name}`; },会被提升(hoisted),可先调用后定义。
-
函数
表达式:const sayHello = function(name) { return `Hello, ${name}`; },不会提升,必须先定义再调用。 - ES6 还支持箭头函数:const add = (a, b) => a + b;它没有自己的 this、arguments,也不可作为构造函数。
作用域:变量可见的边界
JavaScript 有全局作用域、函数作用域和块级作用域(由 let/const 声明引入):
- 用 var 声明的变量只有函数作用域,且存在变量提升和重复声明不报错的问题。
- 用 let 和 const 声明的变量具有块级作用域(如 if、for 内),不存在变量提升,且禁止重复声明。
- 作用域链决定了变量查找顺序:从当前作用域开始,逐层向上查找,直到全局作用域为止。
闭包:记住“出生环境”的函数
当一个函数返回另一个函数,并且返回的函数引用了外部函数的变量,就形成了闭包:
- 闭包让内部函数保有对外部函数作用域中变量的访问权,即使外部函数已执行结束。
- 常见用途包括:模块封装(避免污染全局)、私有变量模拟、回调函数保存状态、防抖节流中的定时器管理。
- 例如:function createCounter() { let count = 0; return () => ++count; } const counter = createCounter(); console.log(counter()); // 1 —— count 被闭包持续持有。
注意内存与实际使用
闭包强大但需谨慎使用:
- 过度保留大对象或 DOM 引用可能导致内存泄漏,尤其在事件监听或定时器中未清理时。
- 调试时可通过浏览器开发者工具的 Scope 面板查看闭包变量。
- 现代 JS 引擎会自动回收不再被任何闭包引用的变量,不必手动“释放”,重点是避免意外长期持有。

表达式:const sayHello = function(name) { return `Hello, ${name}`; },不会提升,必须先定义再调用。






