闭包

来源:互联网 发布:史上最恶搞游戏之网络 编辑:程序博客网 时间:2024/06/05 11:07

  闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的常见方式就是在个函数内部创建另一个函数。在一个函数内部定义的函数将包含函数(即外部函数)的活动对象添加到它的作用链中,这样通过内部函数可以访问外部函数的局部变量。通过闭包可以突破作用域链,将函数内部的变量和方法传递到外部。


  在内部函数被返回后,它的作用域链被初始化为外部函数的活动对象和全局变量的对象。这样,内部函数就可以访问在外部函数中定义的变量。更重要的是,外部函数在执行完毕后,其活动对象也不会被销毁,因为内部函数的作用域仍然在引用这个活动对象,即他的活动对象仍然会留在内存中,直到内部函数被销毁后,外部函数的活动对象才会被销毁。



注意: 闭包只能取得包含函数中任何变量的最后一个值闭包所保存的是整个变量对象,而不是某个特殊的变量。

   for(var i = 0; i < 5; i++){        setTimeout(function(){            console.log(new Date(),i, 'B');         },1000);    }    console.log(new Date(),i,'A');

代码运行结果为:

Thu Aug 10 2017 20:14:28 GMT+0800 (中国标准时间) 5 "A"Thu Aug 10 2017 20:14:29 GMT+0800 (中国标准时间) 5 "B"Thu Aug 10 2017 20:14:29 GMT+0800 (中国标准时间) 5 "B"Thu Aug 10 2017 20:14:29 GMT+0800 (中国标准时间) 5 "B"Thu Aug 10 2017 20:14:29 GMT+0800 (中国标准时间) 5 "B"Thu Aug 10 2017 20:14:29 GMT+0800 (中国标准时间) 5 "B"

  表面上看,B处应该输出0、1、2、3、4,即每次调用内部函数时,i 的取值,但实际上,每个函数都返回的是5。因为每次调用setTimeout函数它们引用的都是同一个变量 i 。当for执行完后,变量 i 的值是5,此时每个函数都引用着保存变量 i 的同一个变量对象,所以每个函数内部 i 的取值都是5.



若想在B处输出0、1、2、3、4,则通过需要创建另一个匿名函数强制让闭包的行为符合预期,如下所示:

   for(var i = 0; i < 5; i++){        (function(num){            setTimeout(function(){                console.log(new Date(),num, 'B');               },1000);        })(i)    }    console.log(new Date(),i,'A');

代码运行结果为:

Thu Aug 10 2017 20:29:09 GMT+0800 (中国标准时间) 5 "A"Thu Aug 10 2017 20:29:10 GMT+0800 (中国标准时间) 0 "B"Thu Aug 10 2017 20:29:10 GMT+0800 (中国标准时间) 1 "B"Thu Aug 10 2017 20:29:10 GMT+0800 (中国标准时间) 2 "B"Thu Aug 10 2017 20:29:10 GMT+0800 (中国标准时间) 3 "B"Thu Aug 10 2017 20:29:10 GMT+0800 (中国标准时间) 4 "B"

可以注意到A先输出,大约等待1s后,5个B几乎同时输出。

还可以使用 let 修改 for 循环中的变量定义,使 B 处达到预期结果。代码修改见 ES6 —(let、const)。

原创粉丝点击