被众多程序员誉为js难度第一的闭包
码文不易,请未来的大厂程序员们动动发财的小手点点赞
前言
在程序员们聊到js时,应该都会被闭包的概念所吸引,因为闭包被誉为js最难理解的知识。 既然如此,我们就去攻克它
闭包是什么
- 根据js词法作用域的规则,内部函数总是能访问外部函数中的变量,当通过调用一个外部函数返回的一个内部函数后,即使外部函数执行已经结束了,但是内部函数引用了外部函数中的变量也依旧需要被保存在内存中,我们把这些变量的集合叫做闭包 我们看个例子
function bar(){
console.log(a);
}
function foo(){
var a =100
bar()
}
var a = 200
foo()
我们在上面已经学习过了作用域
就一步步分解上面的代码
从全局开始,变量a=undefined,foo()=function foo(){},
进入foo()函数a=100,bar()=function bar(){}
进入bar(),变量里没有元素,
开始运行,a=200,foo(),a=100,bar(),console.log(a)
此时应该输出100
让我们看看答案
问题就是在于,bar()的outer指向的是全局,bar()函数并没有在foo函数体里 当改成这样
function foo(){
function bar(){
console.log(a);
}
var a =100
bar()
}
var a = 200
foo()
输出就为100
开始进阶
function add(){
var count = 0;
function foo(){
count++;
return count;
}
return foo;
}
var bar = add()
console.log(bar())
console.log(bar())
console.log(bar())
一步步解析
全局上下文 bar=undefiner,
进入add(),count = undefined,foo()
开始运行:
调用add()函数,运行function foo(),count++,count=1,返回count,foo函数结束,把1赋值给foo返回给add(),bar = add(),console.log(bar()),输出1
连续执行三次,是不是每次都从count=0开始,最后输出1,1,1
我们来看结果
返回的值是1,2,3
在我们的惯用思维下,就应该是1,1,1,但结果是1,2,3,
这就是js中特殊的闭包
在每次console.log(bar())时,都会调用一次add(),在闭包里的count会每次都++
闭包概念
无论何时声明新函数并将其赋值给变量,都要存储函数定义和闭包。闭包包含在函数创建时作用域中的所有变量,它类似于背包。函数定义附带一个小背包,它的包中存储了函数定义创建时作用域中的所有变量。
简化来说,只要一个函数没有被调用,而是用return来返回其函数体中变量的值时,就会产生闭包
其实,用window来将变量放入全局,也是同理。
闭包的作用
- 作用
- 实现公有变量(企业的模块开发)
- 做缓存
- 封装模块,防止全局变量污染
在大型程序的开发中,闭包往往起到非常重要的作用,因为每个人负责一部分功能,难免在设置变量时,变量名会重合,用闭包封装,就会避免被全局变量污染
闭包的缺陷
闭包有个巨大的缺陷,就是会占用栈的内存,如果一个程序使用了大量的闭包方法,就会挤压栈的空间,导致内存泄漏
结语
对闭包概念的理解,是每个程序员都难以逃脱的宿命,希望这篇文章可以给你启发。
转载自:https://juejin.cn/post/7373645836871876618