闭包使用详解

什么是闭包

 

函数即使脱离了它原本所在的词法作用域,也能够访问在词法作用定义的变量。因为函数被return出去了,没有执行一直持有函数的执行期上下文,然后就形成了闭包。闭包 = 执行环境 + 函数

image.png

这个函数 a 可以放在别的文件里面,然后得到的 b 函数,不管你在什么时候调用,都会正确打印「hello,闭包」,一般的 a 函数执行完,hello 变量就会被释放,但是在闭包里面,这个 hello 直到 b 函数执行之前,hello 都不会被释放。应用场景太多了,定时器、防抖按钮 什么的都需要用到闭包,下面我们看看应用场景

应用闭包的主要场合:

定时器

let方式.png

大家很容易就想到输出5个5

 

例一:函数每个一秒返回一个5

for (var i = 0; i < 5; i++) {
  setTimeout(function () {
  console.log(i)
  }, 1000 * i)
  }

上面可以简写为如下:

for (var i = 0; i < 5; i++) {
          var temp =   function () {
                console.log(i)
            }
           setTimeout(temp , 1000 * i)
        }
        temp()

 

例二:每隔1秒返回一个undefine

 for (var i = 0; i < 5; i++) {
            setTimeout(function (i) {
                console.log(i)
            }, 1000 * i)
        }

上面可以简写为如下:

  for (var i = 0; i < 5; i++) {
          var temp=  function (i) {
                console.log(i);
            }
                setTimeout(temp, i * 1000);
            }
            temp()

 

例三:结果是立即输出0,1,2,3,4,

for (var i = 0; i < 5; i++) {
  setTimeout((function(i) {
    console.log(i);
  })(i), i * 1000);
}

image.png

 

如何模拟定时器的方式输出:

 

如何输出01,2,3,4,呢?可以考虑立即执行函数或者let的块级作用于的方式解决

立即执行函数.png

 

输出5个5.png

 

将定事情放在for循环.png

设计私有的方法和变量。(团队合作可以封装代码互不影响)

任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数外部访问这些变量。私有变量包括函数的参数、局部变量和函数内定义的其他函数。

把有权访问私有变量的公有方法称为特权方法(privileged method)。

 function closure(){
            var age =22;
            var resetAge=function(){
                age =20
            }
             var setAge = function (newAge) {
                 age = newAge
            }
            var getAge = function(){
                console.log(age)
                return age
            }
            var obj ={
                resetAge: resetAge,
                setAge: setAge,
                 getAge: getAge
            }
            return obj
        }
       let privateData = closure();
       privateData.getAge();
       privateData.setAge(29)
       privateData.getAge();
       privateData.resetAge();
       privateData.getAge();

简化代码如下:

  function closure() {
            var age = 22;
            //特权方法
            return obj = {
                resetAge: function () {
                    age = 20
                },
                setAge: function (newAge) {
                    age = newAge
                },
                getAge: function () {
                    console.log(age)
                    return age
                }
            }
        }
        let privateData = closure();
        privateData.getAge();
        privateData.setAge(29)
        privateData.getAge();
        privateData.resetAge();
        privateData.getAge();

闭包缺点:内存泄漏

 

闭包会引用包含函数的整个变量对象,如果闭包的作用域链中保存着一个HTML元素,那么就意味着该元素无法被销毁。所以我们有必要在对这个元素操作完之后主动销毁。

闭包中的this对象

在上面这段代码中,obj.getName()()实际上是在全局作用域中调用了匿名函数,this指向了window。

这里要理解函数名与函数功能是分割开的,不要认为函数在哪里,其内部的this就指向哪里。

window才是匿名函数功能执行的环境。

如果想使this指向外部函数的执行环境,可以这样改写:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值