函数表达式本身不创建新作用域,但可通过iife实现私有作用域、通过闭包延长外层变量生命周期,并需避免隐式全局和变量遮蔽。

函数表达式本身不创建新的作用域,但它常被用在能产生独立作用域的上下文中(比如立即执行、嵌套或闭包),从而间接实现对函数作用域的精细控制。
函数表达式默认共享外层作用域
单独写的函数表达式不会自动建立新作用域;它只是把函数赋值给变量,其内部仍沿用定义时所在位置的词法作用域:
- 如果写在全局,内部可访问全局变量;
- 如果写在一个函数里,内部就能访问该函数的局部变量和参数;
- 它不改变作用域链结构,只影响函数何时被调用、是否被保留。
通过立即执行实现私有作用域隔离
把函数表达式包裹在括号中并立刻调用,就形成了“立即执行函数表达式”(IIFE),这是管理作用域最常用的方式:
- 语法上必须加括号或运算符(如!、+、-)来避免解析为函数声明;
- 执行后形成一个一次性作用域,其中声明的var/let/const不会污染外部;
- 适合封装初始化逻辑、隐藏临时变量或避免全局命名冲突。
例如:
!(function () {
let temp = 'private';
console.log(temp); // 可访问
})();
console.log(temp); // ReferenceError: temp is not defined
配合闭包延长作用域生命周期
当函数表达式作为返回值被外部引用,它会携带定义时的作用域链,让外层变量持续存活:
- 即使外层函数已执行完毕,其局部变量仍可通过内部函数访问;
- 这实现了数据封装和状态保持,比如计数器、配置缓存等场景;
- 注意:过度使用可能造成内存无法释放,尤其在频繁创建闭包时。
例如:
function createLogger(prefix) {
return function (msg) {
console.log(`[${prefix}] ${msg}`);
};
}
const infoLog = createLogger('INFO');
infoLog('system started'); // [INFO] system started
避免隐式全局与变量遮蔽
函数表达式中若漏写var/let/const,直接赋值会意外创建全局变量:
- 比如myVar = 10(无声明)→ 挂到window或global上;
- 同名变量在不同嵌套层级中容易引发遮蔽(shadowing),建议用let明确块级作用域;
- ES6 后推荐优先用const声明函数表达式,强调不可重赋值语义。











