认识前端闭包

1、前言:(先介绍一下函数的存储原理)

(1)基本函数存储原理:

  • 首先我们定义一个函数,然后调用,如下:
<script>
        function test(){
            let name = 'yiyi'
            console.log(name)
        }

        test()
</script>
  • 正常我们定义和调用一个函数,存储空间是这样变化的:
  • 看下面这张图,存储空间分为栈区和堆区,栈区主要是存储一些简单数据类型的,堆区放的是复杂类型的数据。
  • 在函数定义阶段,栈区存储了函数名test,堆区存储了函数,这个函数在堆区有个地址,只要是把这个函数地址给了test,所以这个test其实指向的是函数的地址;
  • 在函数调用执行阶段,函数内部的代码临时开一个空间去执行代码,当这个代码执行完以后这个空间就被销毁了,不会长期保留;
  • 这就是基本函数的存储原理;

(2)复杂函数存储原理:

  • 如果想函数调用时创建一个不被销毁的空间,必须满足以下三个条件:
  • 函数要有返回值;
  • 返回值必须是复杂类型;
  • 返回值要赋值给外面的变量;

看代码:

<body>
    <script>
        function test(){
            let name = 'yiyi'
            console.log(name)
            let obj = {
                a:1,
                b:2
            }
            return obj
        }

        var obj1 = test()
        var obj2 = test()
    </script>
</body>
  • 代码中同时满足了三个条件:
  • 接下来我们看看这个函数的存储原理:

  • 满足了三个条件,现在函数调用,代码执行时单独开一个空间,执行,执行完不满足三个条件的简单参数name,空间还是被销毁了,但是因为obj对象满足上面的三个条件,所以代码执行完,空间保留没有被销毁。
  • 代码中我们调用了函数两遍,分别用不同的变量名去接收:obj1和obj2,注意这个obj1和obj2不是同一个对象,只是接收的内容一样而已,它们在调用函数时,分别开了一个独立的空间去执行它们的函数,并不会相互冲突和影响。
  • 当然我们也可以手动销毁,直接将接收返回值的变量(obj1、obj2)赋值为空,空间就会被释放了;
obj1 = null
obj2 = null

2、闭包 

闭包:函数内部返回一个函数,被外界所引用,这个内部函数就不会被销毁回收,内部函数所用到了外部函数的变量也不会被销毁;

看代码:

<script>
        function outer(){
            let name = 'yiyi'
            return function(){
                return name+"111"
            }
        }

        //返回值是内部的函数
        var func = outer()
        
        //打印内部函数的返回值
        console.log(func())
</script>

因为闭包满足上面三个条件,所以空间不会被销毁,而且闭包的优势是:被内部函数应用的外部函数定义的基本变量也不会被销毁,也就是说代码中外部定义的name=“yiyi”不会被销毁。

  • 闭包的优点是:让临时变量永驻内存;
  • 缺点是:不销毁空间,就会造成内存被大量占用,出现内存泄漏,
  • 为了避免这样的情况,我们用完了可以手动销毁:
func = null

闭包的应用:

说了这么多,究竟闭包有什么作用呢,看下面代码:

<script>
        // fetch("http://www.a.com/aaa")
        // fetch("http://www.a.com/bbb")
        // fetch("http://www.b.com/aaa")
        // fetch("http://www.b.com/bbb")
        // fetch("http://www.c.com/aaa")
        // fetch("http://www.c.com/bbb")

        function FetchContainer(url){
            return function(path){
                return fetch(url+path)
            }
        }
        var fetcha = FetchContainer("http://www.a.com")

        fetcha("/aaa").then(res=>res.json()).then(res=>console.log(res))
        fetcha("/bbb").then(res=>res.json()).then(res=>console.log(res))
        fetcha("/ccc").then(res=>res.json()).then(res=>console.log(res))
        fetcha("/ddd").then(res=>res.json()).then(res=>console.log(res))


        fetcha = null
</script>
  • 如果我们想访问注释那些网站,闭包就起到了作用;
  • 首先上面符合三个条件,所以url不会被销毁,所以我们每次在给fetcha传接口的时候,可以省略前面一长串的,因为url不会被销毁,所以我们下面都可以继续用;
  • 用完需要手动销毁,就可以把fetcha赋值为null;

闭包的应用:函数柯里化;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌一一

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值