js之深入理解闭包

/*
  闭包:
     mdn对闭包的定义是闭包是能够自由访问变量的函数
     
     那什么是自由变量呢?
        自由变量是指再函数中使用的,但既不是函数参数也不是函数局部变量的变量,
        
    由此我们可知道,闭包是由两部分组成:
        闭包=函数+函数能够自由访问的变量
    我们可以举个例子来看下:
*/
  var a=41
   function kop(){
       console.log(a)
   }
  kop()//所以,所有含的函数都是闭包,只是用的好与不好的区别,会不会造成变量的污染等一系列问题
  
  /*
    我们可以来看下关于代码是怎么执行上下的:如下面的例子
  */
 var scope = "global scope";
 function checkscope(){
     var scope = "local scope";
     function f(){
         return scope;
     }
     return f;
 }
 
 var foo = checkscope();
 foo();
 /*
     执行顺序:
        1.首先javascript会进去全局代码,创建全局的执行上下文,全局上下文执行压入执行上下文栈
        2.全局执行上下文初始化
        3.执行checkscope()函数,然后创建checkscope()函数执行上下文,checkscope()函数执行上下文栈
        4.checkscope()函数创建上下文栈,初始变量,this,作用域链,对象等
        5.checkscope()函数执行完毕之后,checkscope()执行上下文从执行上下文中弹出
        6.执行f函数,然后创建f函数上下文,f函数执行上下文栈
        7.f函数执行上下文初始化,创建变量对象,作用域链,对象等
        8.f函数执行完毕,f函数从上下文栈中弹出
        
    看了以上的执行顺序我们会知道,当执行f函数的时候,checkscope()函数已经销毁了,为什么f函数还能访问checkscope()函数呢?
因为在执行f函数的时候维护了一个作用域链: 
        fContext = {
            Scope: [AO, checkscopeContext.AO, globalContext.VO],
        }
        
      就是因为由这一个作用域链,所以f函数仍然可以读取到checkscope()函数的值
      
      所以我们可以看下从实践角度来说的闭包的定义:
          1.即使创建他的上下文已经销毁,它仍然存在,(比如函数从父函数中返回)
          2.在代码中引入了自然变量
 */
      var data = [];
      
      for (var i = 0; i < 3; i++) {
          //声明一个函数,并马上调用这个匿名函数就叫做立即执行函数;也可以说立即执行函数是一种语法,让你的函数在定义以后立即执行
          //这里的function就是一个立即执行函数
          /*
            立即执行函数的语法:
                第一种: 匿名函数包括在括号里面,后面根一个小括号
                  (function(){})()
                 第二种:匿名函数包裹在括号里面,小括号跟在函数后面
                 (function(){}())
          */
        data[i] = (function (i) {
            console.log(i)
              return function(){
                  console.log(i);
              }
        })(i);
      }
       /**
        当执行到data[0]()的时候,此时for循环已经执行完毕了,也销毁了,因为由作用域链的存在,
        所以还是可以访问到for循环的值的,但是此时的作用域链上的值都是一样的,所以for循环到最后的值是一样的,
        而我们使用立即执行函数,就是相当于改变的作用域链的指向,声明这个函数就会马上调用,所以此时里面成为一个
        闭包,一个作用域,用来报存不同的i值,所以会不一样
        
        立即执行函数会形成一个单独的作用域,我们可以封装一些临时变量或者局部变量,避免污染全局变量
        */
      
      data[0]();
      data[1]();
      data[2]();

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值