JS闭包

JS闭包

先贴一段代码,如下:

	function Test(){
		var arr = [];
		for(var i = 0; i < 10; i++){
			arr[i] = function () {
				console.log('打印:' + i )
			}
		}
		return arr;
	}
	var myArr = Test();
	//在我的想象中,函数执行结果应该是1 2 3 4 .... 9,
	//但是事实上全是10, 为什么?
	for(var j = 0; j < 10; j++){
		myArr[j](); 
	}

在这里插入图片描述
1,为什么结果是输出10个10而不是0~9?
分析上述代码,当Test()函数执行的前一刻,会生成函数的执行期上下文AO(Active Object)
此时Test的AO里面有var arr,var i,在函数执行的过程中i循环++ = 10,并循环时向arr的第i位
添加了一个函数,循环结束,将arr抛出Test函数,此时Test执行完毕,销毁自己的执行期上下文
但是在Test函数执行快要结束的前一刻,arr被return出来,此时arr里面保存了10个function,并且
这些函数是在Test里面出生的,拥有Test函数的执行期上下文AO,所以Test函数执行完成时销毁他自己的AO却别arr保存了出来,此时的作用域链是无法释放的,以至于形成了闭包,
简而言之,闭包就是在函数内部定义函数,并把内部函数保存到了外面来执行,此时内部函数使用的执行环境还是父函数的环境,虽然父函数被销毁了,但是它的AO无法销毁,被内部函数保存到了外部。

以上代码在执行完Test的时候 i的值 = 10;所以Test的AO里面i = 10;又因为Test的AO被arr保存了出来,所以在执行arr的时候console.log(‘打印’ + i) 的时候arr函数也会生成一个自己的AO 但是它的AO里面没有i 所以它会向它作用域链的上一环寻找,而上一环正是Test的AO 所以打印 i = 10;

2,如何解决此类问题?
通过代码可以看出通过for循环生成10个function 形成了一个1对10的闭包,解决这个问题,可以把问题转化成10对10的闭包问题,利用立即执行函数可解决

	function Test(){
		var arr = [];
		for(var i = 0; i < 10; i++){
			/***
			**	因为立即执行函数是立即执行的   把i当着实参传入立即执行函数
			**	此时立即执行函数形成了自己的AO  所以此时arr[j]的执行环境是立即执行函数的AO
			***/
			(function (j){
				arr[j] = function () {
					console.log('打印:' + j )
				}
			}(i))	
		}
		return arr;
	}
	var myArr = Test();
	//在我的想象中,函数执行结果应该是1 2 3 4 .... 9,
	//但是事实上全是10, 为什么?
	for(var j = 0; j < 10; j++){
		myArr[j](); 
	}

在这里插入图片描述
3,闭包的一些作用及危害
作用:

  1. 实现变量的私有化
  2. 在内存中维持一个变量,可以做缓存

危害:

  1. 由于闭包造成作用域链的不释放,会占用多余的内存,造成内存泄漏
  2. 其次由于闭包涉及跨域访问,所以会导致性能损失
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值