前端——闭包

目录

闭包的概念

闭包的特性

闭包的用途

1、封装私有变量

2. 做缓存

闭包的缺点


闭包的概念

首先,我们来看一下官网对于闭包的解释:

闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中,闭包会随着函数的创建而被同时创建。闭包 - JavaScript | MDN

读起来不太好理解,实际上翻译成白话文就是:在一个作用域中可以访问另一个函数内部的局部变量的函数。

下面是一个闭包基本使用:

function makeFunc() {
    var name = "Mozilla";
    function displayName() {
        alert(name);
    }
    return displayName;
}

var myFunc = makeFunc();
myFunc();

可以发现在displayName这个作用域下访问了另外一个函数makeFunc下的局部变量name

闭包的实现,实际上是利用了JavaScript中作用域链的概念,简单理解就是:JavaScript中,如果在某个作用域下访问某个变量的时候,如果不存在,就一直向外层寻找,直到在全局作用域下找到对应的变量为止,这里就形成了所谓的作用域链。

闭包的特性

  • 闭包可以访问到父级函数的变量
  • 访问到父级函数的变量不会销毁

闭包的用途

1、封装私有变量

闭包可以用于封装私有变量,以防止其被外部访问和修改。封装私有变量可以一定程度上防止全局变量污染,使用闭包封装私有变量可以将这些变量限制在函数内部或模块内部,从而减少了全局变量的数量,降低了全局变量被误用或意外修改的风险。

在下面这个例子中,调用函数,输出的结果都是1,但是显然我们的代码效果是想让count每次加一的。

function add() {
    let count = 0;
    count++;
    console.log(count);
}
add()   //输出1
add()   //输出1
add()   //输出1

一种显而易见的方法是将count提到函数体外,作为全局变量。这么做当然是可以解决问题,但是在实际开发中,一个项目由多人共同开发,你不清楚别人定义的变量名称是什么,这么做有点冒险,有什么其他的办法可以解决这个问题呢?

function add(){
    let count = 0
    function a(){
        count++
        console.log(count);
    }
    return a
}
var res = add() 
res() //1 
res() //2
res() //3

答案是用闭包。在上面的代码示例中,add函数返回了一个闭包a,其中包含了count变量。由于count只在add函数内部定义,因此外部无法直接访问它。但是,由于a函数引用了count变量,因此count变量的值可以在闭包内部被修改和访问。这种方式可以用于封装一些私有的数据和逻辑。

2. 做缓存


函数一旦被执行完毕,其内存就会被销毁,而闭包的存在,就可以保有内部环境的作用域。

function foo(){
    var myName ='张三'
    let test1 = 1
    const test2 = 2 
    var innerBar={
        getName: function(){
            console.log(test1);
            return myName
        },
        setName:function(newName){
            myName = newName
        }
    }
    return innerBar
}
var bar = foo()   
console.log(bar.getName()); //输出:1 张三
bar.setName('李四')
console.log(bar.getName()); //输出:1 李四

这里var bar = foo() 执行完后本来应该被销毁,但是因为形成了闭包,所以导致foo执行上下文没有被销毁干净,被引用了的变量myName、test1没被销毁,闭包里存放的就是变量myName、test1,这个闭包就像是setName、getName的专属背包,setName、getName依然可以使用foo执行上下文中的test1和myName。

闭包的缺点

如果不是某些特定任务需要使用闭包,在其它函数中创建函数是不明智的,因为闭包在处理速度和内存消耗方面对脚本性能具有负面影响。这会导致变量不会被垃圾回收机制回收,造成内存消耗以及对于不恰当的使用闭包可能会造成内存泄漏的问题。

因此我们在使用闭包时需要特别注意内存泄漏的问题,可以用以下两种方法解决内存泄露问题:

1.及时释放闭包:手动调用 闭包函数,并将其返回值赋值为null,这样可以让闭包中的变量及时被垃圾回收器回收。
2.使用立即执行函数:在创建闭包时,将需要保留的变量传递给一个立即执行函数,并将这些变量作为 参数传递给闭包函数,这样可以保留所需的变量,而不会导致其他变量的内存泄漏。

文章参考:https://juejin.cn/post/7263628964748197948?searchId=202409181814262652E22A762C8251C03B

https://zhuanlan.zhihu.com/p/703373072

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值