JS闭包不理解?一杯咖啡的时间带你轻松理解闭包!

一、为什么闭包很重要?

闭包是JavaScript的灵魂级概念!无论是:

  • 面试高频考点(10个面试9个问)
  • 日常开发(回调函数、模块化、防抖节流)
  • 框架原理(React Hooks、Vue Composition API)

不懂闭包 = 学不好JS

接下来用最通俗的方式帮你彻底掌握!


闭包的优缺点

优点 缺点
封装私有变量,增强数据安全性 过度使用可能导致内存泄漏
实现高阶函数(如柯里化、装饰器) 闭包变量无法被垃圾回收机制释放
解决循环中的异步问题 可能影响代码可读性

二、闭包的生活化比喻

想象你有一个魔法背包🎒:

  1. 装东西:把书本(变量)放进背包(外层函数)
  2. 交给朋友:把背包交给朋友保管(返回内层函数)
  3. 随时取用:朋友即使在你离开后(外层函数执行完毕),仍能打开背包使用书本(访问变量)

三要素

👉 背包里的物品 = 外部函数的变量

👉 获得背包的朋友 = 内部函数

👉 魔法契约 = 闭包规则


三、闭包的双层定义

官方版 :函数能够访问并记住其词法作用域,即使该函数在父级作用域外执行
人话版:内部函数随身携带出生地(外层函数)的变量,走到哪里都能用


四、闭包的核心原理

1. 词法作用域(出生决定论)

javascript 复制代码
function outer() {
    const phone = "iPhone15"; // 出生时自带的手机
    function inner() {
        console.log(phone); // 永远记得自己出生时有什么
    }
    return inner;
}
  • 函数作用域在定义时确定,和在哪里执行无关
  • 内部函数像婴儿记得母亲(外部函数)的样貌

2. 垃圾回收机制(生存法则)

javascript 复制代码
function outer() {
    const data = "重要资料";
    return function() { 
        console.log(data) 
    };
}

const func = outer(); // 执行完毕
func(); // 仍然能打印"重要资料"
  • JS会自动清除不再使用的变量
  • 闭包会死死抓住用到的变量,不让系统回收

五、闭包实战训练营

案例1:私人保险箱

javascript 复制代码
function createSafe() {
    let money = 0; // 保险箱里的钱,外人无法直接接触

    return {
        deposit: (amount) => {
            money += amount;
            console.log(`存入${amount},余额${money}`);
        },
        checkBalance: () => {
            console.log(`当前余额:${money}`);
        }
    };
}

const mySafe = createSafe();
mySafe.deposit(100); // 存入100,余额100
mySafe.checkBalance(); // 当前余额:100
// 无法直接修改money变量!

闭包部分 :返回的depositcheckBalance方法形成了闭包,锁住了money变量

案例2:网页点击统计

javascript 复制代码
function setupCounter() {
    let count = 0;
    const btn = document.getElementById('myBtn');
    
    btn.addEventListener('click', function() {
        count++;
        console.log(`这是第${count}次点击`);
    });
}
setupCounter();

闭包在哪里 :点击回调函数记住了count变量,即使setupCounter早已执行完毕


六、必知常见问题

Q1:闭包必须return函数吗?

不一定! 只要内部函数逃逸到外部环境,就会形成闭包:

javascript 复制代码
// 情况1:定时器
function startTimer() {
    const startTime = Date.now();
    setInterval(() => {
        console.log(`已运行${Date.now() - startTime}ms`);
    }, 1000);
}

// 情况2:DOM事件
function trackScroll() {
    const scrollY = window.scrollY;
    window.addEventListener('scroll', () => {
        console.log(`当前滚动位置:${scrollY}`);
    });
}

Q2:闭包会导致内存泄漏吗?

不一定!现代浏览器很聪明

只有当闭包长期持有不再需要的大数据时才会泄漏:

javascript 复制代码
// 危险操作!
function leakMemory() {
    const hugeData = new Array(1000000).fill('⚠️'); // 1MB数据
    return function() {
        console.log('这个闭包根本用不到hugeData!');
    };
}

const func = leakMemory(); // hugeData被无意义地保留着

安全操作指南

javascript 复制代码
// 正确做法:及时清理
let usefulClosure = createSafe();
// 使用完毕后...
usefulClosure = null; // 斩断引用链

// 推荐做法:避免保留无用数据
function safeExample() {
    const usefulData = "需要的数据";
    const tempData = "临时数据";
    
    return function() {
        // 只使用usefulData
        console.log(usefulData);
        // tempData在闭包形成后可以清理
        tempData = null; // 手动释放
    };
}

七、闭包使用口诀

  1. 需要长期存数据 → 大胆用闭包
  2. 不再使用的闭包 → 及时设null
  3. 大对象要小心 → 用完就清理
  4. 避免过度使用 → 按需取用

现在你已经是闭包小达人了!试着写个累计计算器练练手吧~ 🚀

遇到问题别担心,多写多调试才是硬道理!

相关推荐
遂心_41 分钟前
深入解析前后端分离中的 /api 设计:从路由到代理的完整指南
前端·javascript·api
@大迁世界1 小时前
第7章 React性能优化核心
前端·javascript·react.js·性能优化·前端框架
DownToEarth1 小时前
H5实现获取当前定位
javascript
前端Hardy1 小时前
HTML&CSS:惊艳!科技感爆棚的登录页面代码解析
前端·javascript·html
我是哈哈hh1 小时前
【AJAX项目】黑马头条——数据管理平台
前端·javascript·ajax·前端框架·axios·proxy模式
Ronin-Lotus2 小时前
上位机知识篇---AJAX
前端·javascript·ajax
Sherry0072 小时前
CSS Grid 交互式指南(译)(下)
css·面试
拾光拾趣录2 小时前
箭头函数 vs 普通函数:从“this 指向混乱”到写出真正健壮的代码
前端·javascript
一只毛驴2 小时前
浏览器中的事件冒泡,事件捕获,事件委托
前端·面试
一只叫煤球的猫2 小时前
你真的处理好 null 了吗?——11种常见但容易被忽视的空值处理方式
java·后端·面试