闭包:JavaScript里的江湖规矩

老有人问我闭包是啥。说实话,这玩意儿就跟江湖黑话似的,懂的人相视一笑,不懂的听得云里雾里。

我刚开始写JS那会儿,最怕面试官问闭包。现在?呵,闭包就是我每天吃饭的家伙。

咱们说人话

闭包说白了就是:函数记住了它出生的地方

打个比方。你老家院子里有棵枣树,后来你搬城里住了。但不管走到哪儿,你都记得老家那棵枣树。这就叫闭包——函数离开了自己的诞生地,却依然记得当初的环境。

function 老家的院子() {
  let 枣树 = '大红枣'
  
  return function() {
    console.log(我还记得这棵枣树上的:${枣树})
  }
}

const 记忆 = 老家的院子()
记忆() // 输出:我还记得这棵枣树上的:大红枣

看见没?记忆()这个函数已经离开了老家的院子(),但它居然还记得院子里那棵枣树上的枣是什么品种。

这玩意儿有啥用?

用处大了去了!最常用的就是藏点小秘密。

比如你想做个计数器,但又不想让别人随便改你的数字:

function 创建计数器() {
  let 计数 = 0
  
  return {
    加一: () => {
      计数 += 1
      return 计数
    },
    减一: () => {
      计数 -= 1
      return 计数
    }
  }
}

const 我的计数器 = 创建计数器()
console.log(我的计数器.加一()) // 1
console.log(我的计数器.加一()) // 2
console.log(我的计数器.减一()) // 1

外面的世界根本动不了计数这个变量,只有通过加一()减一()这两个方法才能操作。这就叫封装,懂吧?

坑也是真坑

闭包用不好也挺要命的。最常见的就是循环里创建函数:

for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i) // 全输出3,惊喜不?
  }, 100)
}

为啥全输出3?因为等setTimeout回调执行的时候,循环早跑完了,i已经变成3了。

解决办法?用let代替var,或者再用个闭包:

for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i) // 0, 1, 2
  }, 100)
}

实战中的闭包

我现在写代码,闭包几乎无处不在:

  1. 事件处理:记住点击的是哪个按钮
  2. 模块模式:藏私有变量,只暴露该暴露的
  3. 柯里化:先配置一部分参数,剩下的以后再说
  4. 防抖节流:控制函数执行频率

说白了,闭包就是JS的函数在说:“我这人恋旧,走到哪儿都带着老家的回忆。”

所以下次有人问你闭包是啥,你就告诉他:函数背着自己的小书包,书包里装着它出生时的环境

懂了没?没懂就再多写几行代码,写多了自然就明白了。JS这东西,光看不练假把式。

posted @ 2025-08-25 15:47  深圳蔓延科技有限公司  阅读(10)  评论(0)    收藏  举报