什么是闭包?你真的了解吗?

本文详细讲解了JavaScript中的闭包概念,包括何时使用、如何创建和利用闭包来保护变量,以及闭包形成的原因。通过实例分析了标准闭包和反复调用外层函数时的闭包行为。
摘要由CSDN通过智能技术生成
什么时候使用闭包?

    想重用一个变量,但是又想保护变量不被篡改 (本质:给一个函数保护一个专属的变量,仅          函数自己可反复使用,别人无法使用 )

如何使用闭包?
  1.  用外层函数包裹内层函数 和要保护的变量
  2.  外层函数将内层函数return到外层函数内部
  3.  外部的使用者,需要调用外层函数,获得返回的内层函数对象,并将内层函数对象保存在变   量中 反复使用
闭包形成的原因?

     外层函数调用后,外层函数的作用域对象被内层函数的作用域链引用着无法释放,成为内层函       数的私有财产,就形成了闭包

function  parent(){   //外层函数 --- 妈妈
   var total = 1000;   //要保护的变量 ---红包
   return function (money){ //内层函数 --- 小孩
     total-=money;
     console.log(剩余:total)
   }
}
var pay = parent(); ---妈妈生孩子 每调用一次函数创建一个红包(要保护的变量)
pay(100);
pay(100);      //反复调用 时和妈妈再无关系 (闭包保护变量的方式)
pay(100);

标准闭包情况:(生一个孩子的情况) 

生两个孩子的情况:

   因为每调用一次外层函数 就会创建一个保护的变量
   所以第二次 var pay2 的时候就会重新创建一个保护的变量 var total = 1000
   所以 调用pay2(10) 的返回值为990

笔试题:

function fun (){     //外层函数 
   for( var i = 0; arr=[]; i<3; i++){  //var i =0是循环变量 循环执行了三次 0 1 2因为i<3 
     arr[i] = function(){ console.log(i) } //内层函数 孩子,目前仅创建了孩子没有调用
   }  //此循环执行了三次 相当于生了三个孩子 结果为 arr[0] = function(){}
                                                arr[1] = function(){}   
                                                arr[2] = function(){}
                                           
   return arr;
}
var funs = fun(); //此时的var funs变量 是fun()函数的return返回值 也就是指的 return的 arr
             所以现在的funs就是一个这样的数组 [ function(){} , function(){} , function(){} ] 
             同上arr[0]...
             调用了一次外层函数 就会创建一次函数作用域变量 此时的 i = 3 因为当循环不再能执行的时候 
             i=3 假设i=2循环可以正常执行 只有i=3的时候才能退出循环 所以在上边return arr;前 i= 3
             所以下边孩子共用一个变量 i=3

funs[0]();//3  //funs[0] 就是 数组里的第一个函数function(){} 加()调用
funs[1]();//3  //funs[1] 就是 数组里的第二个函数function(){} 加()调用
funs[2]();//3  //funs[2] 就是 数组里的第三个函数function(){} 加()调用

注意:外层函数 向外边抛出几个内层函数对象 有三种方式
1. return function(){ xxxxx }
2. 还可以通过直接给变量赋值的形式,向外抛出一个函数 
 (在js中强行给未声明的变量赋值,会自动在全局创建该变量)
3. return一个对象或数组,在对象和数组中包含多个函数定义 (上边的funs笔试题)

判断是否是否属于闭包?有三个条件
1.外层函数包裹要保存的变量 和 使用变量的内层函数
2.外层函数 将 内层函数返回到外部 (上边解释有三种方法将内层函数抛出)
3.调用外层函数 获得内层函数对象 并保存在变量中 反复使用

// 看看是否符合闭包条件 ?
// 1. 外层函数包裹要保存的变量和使用变量的内存函数

function fun (){   //外层包裹的函数   
    var n = 999;   //要保存的变量
    nAdd=function(){ n++ }; //内层函数 
                            //(在js中强行给未声明的变量赋值,会自动在全局创建该变量nAdd)
    //2. 外层函数将内层函数返回到外部
    return function(){      //内层函数
      console.log(n)
    }
}
//fun()返回(return)什么, getFun就会拿到什么 也就是 function(){xxxx}
var getFun = fun();  //3. 调用外层函数 获得了内存函数的对象,并保存在了变量中反复使用
                     //因为只调用了一次外层函数 所以创建一个作用域变量 以下三个孩子共用
getFun(); //第一次调用 n输出999
nAdd();   //在调用nAdd()会对n++ 也就+1=1000  
getFun(); //因为只对一个作用域变量进行操作 所以在此调用getFun() 输出n 也就为1000


//如果函数外边有个全局变量

反复调用外层函数的情况:
   每调用一次外层函数 就会创建一次受保护的局部变量 和函数

function f1 (n){ //外层函数
    //形参 n 是 f1 的局部变量,也是受保护的变量
   function f2(){ alert(n) }; 
   return f2; //返回内层函数
}

var num = new Array();
for( var i = 0;i < 4; i++){
   num[i]=f1(i)   //这里进行了赋值 就会有变量提升 function f1()由原来的位置提到前边
   //这里 把外层函数 放在了循环里 循环了四次 所以就调用了四次 以下四个生成的函数和闭包互不干扰!
   //第一次调用外层函数 i=0 num[0]=f1(0) 所以此时形参n为0 f2(){ alert (0) }
   //第二次调用外层函数 i=1 num[1]=f1(1) 所以此时形参n为1 f2(){ alert (1) }
   //第三次调用外层函数 i=2 num[2]=f1(2) 所以此时形参n为2 f2(){ alert (2) }
   //第四次调用外层函数 i=3 num[3]=f1(3) 所以此时形参n为3 f2(){ alert (3) }
}

//function f1 (n){
//   function f2(){ alert(n) };
//   return f2;
//}

num[2](); //2
num[1](); //1
num[0](); //0
num[3](); //3

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值