js 闭包 内存泄漏

闭包是什么

闭包是一个函数(一个作用域可以访问另一个作用域的局部变量)

闭包的产生

但凡是内部的函数 被保存到了外部 就一定产生了闭包
多个函数嵌套 把里面的函数保存到了外部

闭包的缺点

闭包会导致原有作用域链不释放,造成内存泄漏(占用内存)

闭包的作用

延申了变量的作用范围
实现公有变量 :累加器
可以做缓存(存储结构)
可以实现封装,属性私有化
模块化开发,防止污染全局变量 案例

累加器(不依赖外部变量)

function add(){
	var count = 0;
	function demo(){
		count++;
		console.log(count)
	}
	return demo;
}
var counter = add();
counter(); //1
counter(); //2
counter(); //3
counter(); //4

存储结构

function test (){
	var num =100
	function a(){
		num++
	}
	function b(){
		num--
	}
	return [a,b]
}
var myArr = test();
myArr[0](); //101
myArr[1](); //100

产生问题

function test(){
	var arr = [];
	for(var i=0;i<10;i++){
		arr[i] = function(){
			console.log(i)
		}
	}
	return arr
}
var myarr = test()
for(var i=0;i<myarr.length;i++){
	myarr[i]()
}

//结果输出
//10 10 10 10 10 10 10 10 10 10

//分析
test 定义(defined) test.[[scope]] ==> 0:GO
test 执行(doing)   test.[[scope]] ==> 0:testAO
									  1:GO
									  
test 执行(doing) 预编译
1,创建AO对象
2,把函数内的变量行程挂载到AO对象 赋值undefined
 testAO{
 	arr:undefined,
 	i:undefined
 }
3,形参实参统一
4,找到函数声明,并赋值函数体
 
 for循环
 i:0
 testAO{
 	arr:[0:function(){...},....]
 	i:0
 }	
 .....
 i=9
 testAO{
 	arr:[0:function(){...},....]
 	i:9
 }	
 i=10
 循环终止
 testAO{
 	arr:[0:function(){...},....]
 	i:10
 }	
	
myarr[i]()调用
console.log(i);//10

arr[i] 与 函数表达式的 i
arr[i] 是变量 立即执行 获取执行时的i
函数表达式的 i 函数没有执行的时候 是引用值 i值不确定 
执行时 获取函数表达式执行时的i
 									  

解决问题 就想输出 0~9

// 立即执行函数
function test(){
	var arr = [];
	for(var i=0;i<10;i++){
		(function(j){
			arr[j] = function(){
				console.log(j)
			}
		})(i)
		// 
	}
	return arr
}
var myarr = test()
for(var i=0;i<myarr.length;i++){
	myarr[i]()
}
// 0 ~ 9

// 执行过程分析
test 定义(defined) test.[[scope]] ==> 0:GO
test 执行(doing)   test.[[scope]] ==> 0:testAO
									 1:GO
test 执行(doing) 预编译
1,创建AO对象
2,把函数内的变量行程挂载到AO对象 赋值undefined
 testAO{
 	arr:undefined,
 	i:undefined
 }
3,形参实参统一
4,找到函数声明,并赋值函数体	

for循环
i=0
立即执行函数
立即执行函数 定义(defined)   
	创建AO对象 01AO
	把函数内的变量行程挂载到AO对象 赋值undefined
	o1AO{
		j:undfined
	}
	形参实参统一 
	o1AO{
		j:0
	}
	
立即执行函数 执行(doing)   01.[[scope]] ==> 0:01AO{j:0}
									 	   1:testAO{arr:[0:function(){}]}
										   2:GO	
立即执行函数 执行完 销毁执行期上下文 (产生闭包 arr[0]继承了立即执行函数的作用域链 销毁不掉) 销毁立即执行函数

i=1
立即执行函数
立即执行函数 定义(defined)   
	创建一个新的AO对象 o2AO
	把函数内的变量行程挂载到AO对象 赋值undefined
	o1AO{
		j:undfined
	}
	形参实参统一 
	o1AO{
		j:1
	}
	
立即执行函数 执行(doing)   02.[[scope]] ==> 0:02AO{j:1}
									 	   1:testAO{arr:[0:function(){}]}
										   2:GO	
立即执行函数 执行完 销毁执行期上下文 (产生闭包 arr[1]继承了立即执行函数的作用域链 销毁不掉) 销毁立即执行函数
					  
。。。。
i=10
循环终止

调用
for(var i=0;i<myarr.length;i++){
	myarr[i]();
	//function(){
	//	 console.log(j)
	//}
}
marr[0]();
marr[0].[[scope]] ==> 0:marr[0]AO 
					  1:01AO{j:0}
查找变量 j (从作用域链顶端依次向下查找 [[scope]] 0->n)
0:marr[0]AO 没有j 找下一级 1:01AO
1:01AO{j:0} 即j=0 

marr[1]();
marr[1].[[scope]] ==> 0:marr[2]AO 
					  1:02AO{j:1}
0:marr[1]AO 没有j 找下一级 1:02AO
1:02AO{j:1} 即j=1
....

结果 0~9

属性私有化

function Per(name,age){
	var page = 0;
	this.name = name;
	this.age = age;
	this.getPage = function(){
		consle.log('page',page);
	}
	this.add = function (){
		page ++ 
	}
}
var per = new Per('per',18)
//page 就是per对象的私有化属性
console.log(per.page);//undfined 访问不到
per.getPage();// 0 只有它自己的方法才能访问

//是因为产生了闭包 函数作用域被保存到了外面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值