闭包

参考:http://www.360doc.com/content/19/0529/15/64276718_838982036.shtml

什么是闭包

闭包是能够读取函数内部定义的变量的函数
函数内部定义的变量,在函数外无法调用到,并且在函数执行完以后,定义变量的内存也会被回收,闭包函数因为是函数内部的子函数,可以访问到上级函数定义的变量,即使上级函数执行完作用域也不会销毁

补充:函数的作用域
js变量分为全局变量和局部变量,在函数内部可以直接调用全局变量,但是函数为不能调用函数内的变量,变量的作用域最多只能是定义时的函数作用域

闭包解决了什么问题

  1. 可以读取函数内部的值
  2. 让函数内定义的变量一直保存在内存中,不会在函数被调用后清除
function addCounter() {
 
let counter = 0
 
const myFunction = function () {
 
counter = counter + 1
 
return counter
 
}
 
return myFunction
 
}
 
const increment = addCounter()
 
const c1 = increment()
 
const c2 = increment()
 
const c3 = increment()
 
console.log('increment:', c1, c2, c3);
 
// increment: 1 2 3

在这段代码中increment实际上就是闭包函数myFunction, 它一共运行了三次,第一次的值是1,第二次的值是2,第三次的值是3。这证明了,函数addCounter中的局部变量counter一直保存在内存中,并没有在addCounter调用后被自动清除。

闭包与setTimeout的应用:如何取到正确的值

for (var i = 0; i < 10; i++) {
 
	setTimeout(function () {
	 
		console.log(i) // 输出结果10个10
 
	}, 1000)
}

上述代码执行流程:for循环为同步任务,正常执行,执行第一次for循环,函数体内只有setTimeout,setTimeout为异步任务中的宏任务,将其置于异步任务队列中等待主线程执行完再执行,此时for循环体中没有其他代码,第一次for循环已经结束,开始第二次for循环,i自增1,以次类推,当for循环完毕,此时主线程上的同步任务已经执行完,开始执行任务队列中的微任务,此例并没有微任务,所以开始第二次事件循环,执行任务队列中的宏任务也就是setTimeout,这时由于for循环已经循环完10次,i的值此时为10,所以setTimeout中打印出来的i值也为10,并且打印10次

正确的取到每次循环的值,如下:

for (var i = 0; i < 10; i++) {
 
	((j) => {
	 
		setTimeout(function () {
		 
			console.log(j) //1-10
		 
		}, 1000)
	 
	})
	(i)
}

上述代码执行流程与上一个例子类似,只不过for循环中是一个function,将循环变量 i 作为形参传给function,function函数体内的实参并不是作为循环变量的i,而是当前 i 的拷贝,所以每次执行function,都会将当前的 i 复制后传递到函数体,以此实现了打印出正确的数字

闭包模拟私有变量

闭包的缺点

  1. 由于闭包会是的函数中的变量都被保存到内存中,滥用闭包很容易造成内存消耗过大,导致网页性能问题。解决方法是在退出函数之前,将不再使用的局部变量全部删除。

  2. 闭包可以使得函数内部的值可以在函数外部进行修改。所有,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值