JavaScript闭包

闭包:定义在一个函数内部的函数被引用到了外部

本质上,闭包是将函数内部和外部连接起来的桥梁。

通常,函数的作用域和它的所有变量都会在函数执行结束后被销毁,但是,在创建了一个闭包以后,这个函数的作用域会一直保存到闭包不存在为止。

这样说可能不理解,让我们看一个经典闭包案例

function test(){
      var arr[];
      for (var i = 0 ;i < 10; i++)
          {arr[i] = function () {document.write(i+" ");} }
return arr;
}
var myArr = test();
for (var j = 0;j < 10;j++)
{
myArr[j]();
}

​

按照常理应该输出0~9吧,实则不然,居然会输出10个10!

因为函数赋值给数组,和外部函数test形成了闭包。

大家可能会有疑问,为什么不是一一对应的呢?i = 0 时,arr[0] =function() {document.write(0+" ")};这个时候应该打印0啊。

这样想是不对的,我来粗略讲解一下这个过程。

1.首先我们从函数调用执行时开始讲起,因为test函数定义过程所需要用的GO我们用不到。

2.在代码块下面,我们使用var myArr =test();调用函数test,在函数执行的前一刻我们进行预编译,函数test会生成一个AO(不了解这一块可以看看我的另一篇博客,JavaScript作用域),其中AO对象里面存了变量i的值。

3.然后函数开始执行,开始定义了一个arr[]数组,然后通过for循环语句赋值给arr[]数组十个函数,相当于:arr[]={function(){},function(){},function(){},......},数组中被赋予了十个一模一样但彼此独一无二的函数,函数内部是啥不知道,这点很关键,JavaScript中,内部对外部是不可见的,在没有调用function(){}之前,系统也不知道函数内部写了啥,因此,这个函数不会立即执行,函数要在被调用的时候才会执行。

4.最后,return arr;把arr return到了test外部,return语句的执行完毕,意味着test函数执行完毕,然后test的AO会被销毁,等待下一次调用,注意,test的AO销毁的前一刻for循环跑完了吧?跑完了是不是要跳出循环?i等于几跳出循环?10吧,那么test的AO中存的值就是i=10,但是,function是被定义在test内部吧,它会直接引用test的AO,它被return到test函数外部了。

5.于是,当调用myArr这个函数表达式的时候,test的AO是不是还在呢?显然不在了,但是数组中每一个function(){}都拿着test的AO呢,于是数组的每一位打印出来都是10

那么如何解决这个闭包带来的困扰呢?

答:用立即执行函数;

function test(){
      var arr[];
      for (var i = 0 ;i < 10; i++)
          (function (j){
         {
            arr[i] = function () {document.write(j+" ");
         } 

          (i));
       }
return arr;
}
var myArr = test();
for (var j = 0;j < 10;j++)
{
myArr[j]();
}

​

​

​

我在arr外层再加一个立即执行函数,然后将i作为实参,j作为形参。

如此一来,数组arr内部有了十个独一无二的立即执行函数,其内部又有一个function,想一想,每次调用,i会传入立即执行函数的形参j,立即执行函数会产生自身的AO,AO内部保存了j的值,所以即便立即执行函数执行完便销毁,其AO也不存在了,但是数组中的function(){}还拿着立即执行函数的AO呢,它会寻找AO内部的j的值,然后在被调用的时候打印出来,他不会去找test函数的AO,因为作用域链的查找是自顶向下的,它自身的AO有,就不会去父级寻找。

对于这一块,本人自身也不是了解得很深刻很清楚,只是愚见,如有错误,望大佬们指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值