闭包(Closure):一个神奇的魔法
闭包大家都不陌生,每个人都对于闭包有或深或浅的认识,本篇就前端闭包一起来聊一聊。 谈到闭包,离不开JavaScript中的作用域和作用域链,作用域(Scope)是指变量、函数和对象的可访问性。换句话说,作用域决定了代码中不同部分的变量、函数和对象的可见性。
作用域
- 全局作用域(Global Scope):在代码任何地方都可以访问;在浏览器中,全局作用域是 window 对象;在 Node.js 中,全局作用域是 global 对象;
var globalVar = "我在全局作用域";
function test() {
console.log(globalVar); // 可以访问
}
console.log(globalVar); // 可以访问
// - 函数作用域(Function Scope):使用 var 声明的变量具有函数作用域;只能在声明它们的函数内部访问;
function myFunction() {
var functionScoped = "我在函数作用域内";
console.log(functionScoped); // 可以访问
}
console.log(functionScoped); // 报错:functionScoped is not defined
// - 块级作用域(Block Scope):使用 let 和 const 声明的变量具有块级作用域;只在 {} 代码块内有效;
if (true) {
let blockScoped = "我在块级作用域内";
const constantVar = "我也是块级作用域";
console.log(blockScoped); // 可以访问
}
console.log(blockScoped); // 报错:blockScoped is not defined
- 模块作用域(Module Scope):ES6 模块中的变量和函数默认在模块内私有;需要使用 export 导出才能被其他模块访问;
- 词法作用域(Lexical Scope):函数在定义时就确定了作用域,而不是在执行时;内部函数可以访问外部函数的变量(闭包);
function outer() {
const outerVar = "外部变量";
function inner() {
console.log(outerVar); // 可以访问外部变量
}
return inner;
}
const innerFunc = outer();
innerFunc(); // 输出:"外部变量"
作用域链
当访问一个变量时,JavaScript 引擎会按照以下顺序查找:
- 当前作用域
- 外层作用域
- 全局作用域
综上所述,闭包究竟是在什么?
结合 函数作用域 和 作用域链得出,闭包是函数与其相关的引用环境组合而成的实体。
- 在JavaScript中,闭包:有权访问另一个函数作用域中的变量的函数,扩张变量的作用域范围,局部变量突破了传统的作用域限制,获得了更长的生命周期。
- 即使外部函数已经执行完毕(外部函数已经返回,其执行上下文已经从执行栈中弹出,但是闭包函数(内部函数)仍然可以访问外部函数中声明的变量。这是因为闭包函数的作用域链仍然保持着对外部函数作用域的引用。)。 外部函数已经执行完毕,引出闭包中必须要了解的另外一个概念:js垃圾回收机制 当JavaScript中的作用域链机制。当函数被创建时,它会保存一个作用域链,这个作用域链包含函数被创建时的作用域中的变量对象。因此,即使外部函数执行完毕,其变量对象仍然被内部函数的作用域链引用,所以不会被垃圾回收。而闭包会保留它们的作用域链,所以不会被销毁。
// 正常函数执行流程
function normalFunction() {
let localVar = '局部变量';
console.log(localVar);
}
normalFunction();
// 输出: "局部变量"
// 函数执行完毕后,localVar 被销毁,无法再访问
// - 闭包的执行流程
function outerFunction() {
let outerVar = '我在外部函数中';
function innerFunction() {
console.log(outerVar); // 访问外部变量
}
return innerFunction; // 返回内部函数
}
// 关键点在这里!
const closure = outerFunction();
// outerFunction 已经执行完毕,按常理 outerVar 应该被销毁
closure(); // 但是这里仍然可以输出: "我在外部函数中"
// outerVar 仍然存在!
简单聊聊闭包的优缺点,感兴趣的话留言评论,大家感兴趣的话可以专门做一篇讲讲优缺点以及实际项目中的运用。
闭包的优点:
✅ 数据封装和私有化
✅ 保持状态和记忆能力
✅ 灵活的函数工厂
✅ 强大的回调处理能力
闭包的缺点:
❌ 潜在的内存泄漏风险
❌ 可能影响性能
❌ 调试复杂度增加
❌ 意外的变量共享问题
谢谢大家观看,走过路过,不要错过了,有钱的捧个钱场,评论区双击666!!!