JavaScript的闭包函数

一.闭包函数的定义

        在JavaScript在存在一个不会销毁的函数空间--闭包,在JavaScript中如果一个函数返回的是一个复杂数据类型,并且被外部的变量引用,那么这个函数空间在执行完成后也不会销毁。

        闭包函数:在一个函数内部定义一个函数,并且这个内部函数还访问了外部函数定义的私有变量,在函数外部还有一个变量接收这个函数的返回值(内部函数),那么这个内部函数就称为闭包函数。

        我们称这个不会被销毁的函数空间称为闭包(整个外部函数的执行空间),返回的函数叫做闭包函数。

1.函数内部返回一个函数

2.内部函数调用了外部函数定义的私有变量

3.外部有一个变量接收这外部函数返回的内部函数

        function a() {
            let num = 100
            return function b() {
                console.log(num)
            }
        }
        let res = a()

        // 从现在开始 res随时可以被调用
        // 在我们的执行空间里 函数a里面的一切都不会被销毁
        // 当res调用的时候,打印的是私有变量num的值

 二.闭包的特点

闭包的特点(优点和缺点并存)

        1 延长了变量的生命周期 

        + 优点:因为执行空间不会销毁,变量也没有销毁

        + 缺点:因为执行空间不会销毁,所以变量一直存在内存中,占用内存

        2 可以访问函数内部的私有变量

        + 优点:利用闭包函数可以访问函数内部的私有变量

        + 缺点:因为执行空间不会销毁,所以变量一直存在内存中,占用内存

        闭包函数的缺点是:“致命的”

        因为当一段内存中有一个不能被销毁的东西一直存在的时候

        那么就会出现内存占用,如果过多的占用内存,就会导致内存溢出

        也就是内存泄漏(内存泄漏(Memory leak)是在计算机科学中,由于疏忽或错误造成程序未能释放已经不再使用的内存,并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费,程序的运行需要内存。只要程序提出要求,操作系统或者运行时就必须供给内存。对于持续运行的服务进程,必须及时释放不再用到的内存。否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃)

三.闭包函数的应用场景

        (1)柯里化函数

                柯里化(Currying)是一种处理多元函数的方法。它产生一系列连锁函数,其中每个函数固定部分参数,并返回一个新函数,用于传回其它剩余参数的功能。在实际应用场景中,函数输入的参数有可能有一部分是相同的,其他的才需要多次输入参数,我们可以使用函数柯里化,将一部分参数固定,减少参数的定位和赋值。

        需求:打印一个我们班学员的信息:我是xx学科 xx班的xxx xxx岁

        // 需求:打印一个我们班学员的信息:我是xx学科 xx班的xxx xxx岁
        function printInfo(xueke, banji, name, age) {
            console.log(`我是${xueke} ${banji}班级 我叫${name} ${age}岁了`)
        }
        printInfo('计算机', '前端', '海绵宝宝', 18)
        printInfo('计算机', '前端', '派大星', 19)
        printInfo('计算机', '前端', '章鱼哥', 19)

        // 改写我上面的这个不好用函数 

        // 对于学科和班级都是一样的我觉得没必要在作为参数传递了
        // 写一个闭包
        function printInfo2(xueke, banji) {

            return function (name, age) {
                console.log(`我是${xueke} ${banji}班级 我叫${name} ${age}岁了`)
            }
        }
        // 生产出一个固定学科和班级的函数
        let print2020 = printInfo2('计算机', '前端')
        // 开辟了一个printInfo空间 xxff11
        // 在这个空间里面进行形参的赋值
        // let xueke = 计算机
        // let banji = 前端
        // 定义函数 function (name, age) {}
        // 把执行空间里面定义的这个函数地址xxff1122 赋值给 print2020
        print2020('海绵宝宝', 18)
        print2020('派大星', 19)
        print2020('章鱼哥', 19)
        // 执行xxff1122函数  自己的name和age,没有看见xueke和banji
        // 我就去上级作用域的执行空间里面xxff11找打了存储xueke和banji的变量
        // 我就直接一起拿来用了

        这里运用了闭包函数在自己的作用域中没有找到需要的值时,会去外部函数寻找,由于闭包函数的函数空间是不会销毁的,所以printInfo的函数执行空间不会销毁,闭包函数都可以访问到我们事先传入的xueke和banji。

 (2)使用闭包模拟私有方法

        在JavaScript中,没有支持声明私有变量,但我们可以使用闭包来模拟私有方法。

var makeCounter= (function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  }
})();

var Counter1 = makeCounter();
var Counter2 = makeCounter();
console.log(Counter1.value()); /* logs 0 */
Counter1.increment();
Counter1.increment();
console.log(Counter1.value()); /* logs 2 */
Counter1.decrement();
console.log(Counter1.value()); /* logs 1 */
console.log(Counter2.value()); /* logs 0 */

上述通过使用闭包来定义公共函数,并令其可以访问私有函数和变量,这种方式也叫模块方式。

         令makeCounter 等于 一个自执行函数,使其直接等于这个函数的返回值(闭包函数),闭包函数是一个对象,对象里面有多个方法,可以访问外部函数的方法,但因为是自执行函数,没有变量引用这个方法,所以无法使用函数内的changeBy方法,相当于只能通过闭包函数来使用这个方法,这就模拟了一个私有方法,只能内部的闭包访问changeBy方法,其他人无法访问。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值