闭包实例
<script>
function A(){
var x = 1;
return function(){
x++;
console.log(x);
}
}
var m1 = A();//第一次执行A函数
m1();//2
m1();//3
var m2 = A();//第二次执行A函数
m2();//2
m1();//4 </script>
- 每次执行A函数时,都会生成一个A的活动变量和执行环境,执行完毕以后,A的执行环境销毁,但是活动对象由于被闭包函数引用,所以仍然保留 所以,最终剩下两个A的变量对象,因此m1和m2在操作x时,指向的是不同的数据
- 为什么连续执行m1的时候,x的值在递增 因为m1在引用的活动对象A一直没有释放(想释放的话可以让m1=null),所以x的值一直递增
- 定义函数m2的时候,为什么x的值重新从1开始了 因为又一次运行了A函数,生成一个新的A的活动对象,所以m2的作用域链引用的是一个新的x值
- m1和m2里面的x为什么是相互独立,各自维持的 因为在定义m1和m2的时候,分别运行了A函数,生成了两个活动对象,所以,m1和m2的作用域链是指向不同的A的活动对象的
闭包涉及作用链的应用
- 解决循环输出问题
for(var i = 1; i <= 5; i ++){
setTimeout(function timer(){
console.log(i)
}, 0)
}
- 方案一:利用IIFE(立即执行函数表达式)当每次for循环时,把此时的i变量传递到定时器中
for(var i = 1;i <= 5;i++){
(function(j){
setTimeout(function timer(){
console.log(j)
}, 0)
})(i)
}
- 方案二:给定时器传入第三个参数, 作为timer函数的第一个函数参数
for(var i=1;i<=5;i++){
setTimeout(function timer(j){
console.log(j)
}, 0, i)
}
- 方案三:使用ES6中的let
for(let i = 1; i <= 5; i++){
setTimeout(function timer(){
console.log(i)
},0)
}
let使JS发生革命性的变化,让JS有函数作用域变为了块级作用域,用let后作用域链不复存在。代码的作用域以块级为单位