关于闭包的一些愚见

闭包(Closure)是JavaScript中的一个重要概念,它允许内部函数访问其外部函数的变量,即使在外部函数执行完毕后仍然可以访问。闭包的核心在于它维持了对包含它的词法环境(作用域链)的引用,这样内部函数就能“记住”并访问外部作用域中的变量。

作用域链:每个函数在执行时都有一个作用域链,这个链包含了函数自身的作用域和包含它的作用域。当函数查找一个变量时,首先在自己作用域中查找,没有就向上搜索作用域链。

结合例子

function createAdder(a) {
  return function add(b) {
    return a + b;
  };
}

在这个例子中,`createAdder`函数返回了一个内部函数`add`。这个`add`函数就是一个闭包,原因如下:

1. 访问外部作用域变量:`add`函数在其定义时,能够访问其外部函数`createAdder`的作用域中的变量`a`。即使在`createAdder`执行完毕后,`add`依然能够记住并访问到这个`a`的值。至于为什么`add`能够记住这个`a`值,就要提到下一个特性


const addTo5 = createAdder(5); // 外部函数createAdder执行完毕
console.log(addTo5(3)); // 输出8,这里尽管createAdder已经执行完毕,但a=5的值被add(作为闭包)保留了下来,并与后来传入的b=3相加。

2. 维持状态:闭包的一个关键用途是维持状态或封装变量。

当一个外部函数执行结束并且将其内部变量通常应该销毁时,只要内部函数(闭包)还被引用,外部函数作用域就不会被销毁。内部函数维持了一个对其外部作用域的引用,这样就可以继续访问那些“应该已经消失”的外部变量。就是上文提到的作用域链,闭包内部作用域找不到的变量,会向外部函数中的作用域查找,就使得外部函数的作用域得以保留。

在这个例子中,`a`的值(5)在`createAdder(5)`调用时确定,并通过闭包机制被`add`函数保留下来。这意味着每次通过`addTo5(某个数)`调用时,实际上都是在原来的基础上(5)加上新的数,而不会丢失最初传给`createAdder`的`a`值,计算出`5+3=8`的结果。这就是“在其外部函数执行完毕后仍可以访问”的含义。

3.数据封装与隐藏

正常情况下,当外部函数执行完毕后,按照一般规则,它的执行环境(包括局部变量)理应被垃圾回收机制回收,因为理论上不再有引用指向这些资源。但是上一个特性说到,存在闭包调用外部函数变量时,因为作用域链,本该销毁的外部函数作用域不会消失,闭包会维持对外部函数作用域中变量的引用。换句话说就是因为闭包而延长了“生命期”,外部函数作用域中变量`a`并没有被立即销毁,直到不再有任何引用指向闭包,导致闭包本身也成为垃圾回收的目标时,这些外部变量才会最终被销毁。这就是闭包能够维持外部函数作用域中变量状态的原因。所以这些变量可以被视为闭包的“私有变量”,因为它们对外部不可直接访问,且生命周期超出了原本预期的范围。

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值