当一个函数的返回值又是一个函数,作为返回值的那个函数叫做闭包
它利用了 作用域的嵌套 ,将原本的局部变量进化成私有变量的环境,叫闭包
一个普通的函数function,如果它可以访问外层作用于的自由变量,那么这个函数就是一个闭包
const f = (function() {
let a = 0;
return function() {
a++;
console.log(a);
};
})();
f();
f();
f();
好兄弟,看!这是一个闭包函数,我们先来分析下这个函数
()() 他叫做立即运行的匿名函数,当一个匿名函数被括起来,然后再在后面加一个括号,这个匿名函数就能立即运行起来
假设我们删去 这个匿名函数,f 是这个最外层的Function,当f()执行时,返回里层的function,
f()()才能调用里层的function
假设去掉,咱们接下往下走
f 其实就是这个函数的返回值 return 出来的函数
第一段代码执行 f 之后,发现a++了,因为里层的函数执行了,那为什么我再最下面console.log(a) 报错呢??
......
console.log(a);
我们都知道let 声明的变量有作用域,不会变量提升,而对于内部的function来说,他是可以拿到a的,因为他们同一作用域(外层),a是个局部变量,所以在外层拿不到;
这也是闭包的 特点 :将原本局部作用域中的局部变量,临时保存起来,不受外部的作用域的影响,可以被外部,反复使用
,刚好说明了我们第二条定义,利用了 “ 作用域的嵌套 ”, 将原本的局部变量进化成私有变量的环境,叫闭包
举两个小例子,让我们看看闭包的使用场景,看完以下两个例子,好兄弟你能不能想起来对闭包的定义
,以及对闭包特点作用
?
var allLi = document.querySelectorAll("li");
for (var i = 0; i < allLi.length; i++) {
console.log(i); //这里我每次都能拿到i
allLi[i].onclick = (function(i) {
return function() {
console.log(i);
};
})(i);
}
// 当我点击的时候,真正触发的时retrun出来的function
// 借助匿名函数帮助我们创建了一个作用域
// 不管里层函数什么时候执行,都能拿到匿名函数里的变量
for (let i = 0; i < allLi.length; i++) {
console.log(i); //这里我每次都能拿到i
allLi[i].onclick = function(i) {
console.log(i)
}
}
// 这个其实也是一个闭包,因为let 有作用域
函数的返回值又是一个函数
利用作用域的嵌套
,将原本的局部变量
进化成私有变量
的环境 ,叫闭包
给不能传参
的 内置函数
的回调参数
传参
let a = "hello";
setTimeout(function(a) {
console.log(a);
}, 1000);
三个问题
直接说明
:上个案例是错误写法,首先setTimeout是window内置的定时器函数,其次他不能传参,因为是内置!!!那有没有解决方案呢?yes!yes!yes! ✌
看答案之前先思考两个问题
setTimeout(fn("hello"), 5000);
function fn(a) {
return function() {
console.log(a);
};
}
说明
:setTimeout是第一个参数是一个函数,因为是内置函数没有接收值,所以不能传参。之所以上个案例打印undifined,是因为上一个函数没有返回值,返回值的标志就是retrun。 既然这样,那我们把这个函数拿出来,而且retrun出去,哎嘿,巧了不是,意外写了个闭包,呐呐,这就是闭包使用场景二:给不能传参
的 内置函数
的回调参数
传参 ✌ ,这一刻你有没有爱上闭包??
垃圾回收机制
。比如我们电脑桌上的回收站,他是先保存到一个临时空间,如果再使用就可以重复使用,确定不用最终删除函数的定义作用域
,和函数的执行上下文 (作用域链)
,不管函数在哪里执行,函数都可以操作自身定义域中存在的变量
你学废了吗?
谢谢阅读,谢谢点赞并关注(没错我就要道德绑架你!)
1. function foo(){
2. function bar(){
3. console.log('吃饭饭')
4. }
5. return bar
6. }
7. var fn=foo()
8. fn()
代码:
foo:地址
;第七行,发现是个变量, GO 存放一个 fn:undi
1. function foo(){
2. var name='haha'
3 function bar(){
4 console.log('吃饭饭' , name)
5 }
6 return bar
7 }
8 var fn=foo()
9 fn()
一个普通的函数function,如果它可以访问外层作用于的自由变量,那么这个函数就是一个闭包
自由变量
会在捕捉时被确定,这样即使脱离了捕捉时的上下文,它也能照常运行 var name = '夏夏'
function my(){
console.log(name)
}
根据1234定义来说,当一个函数内部访问到外部的变量就成为闭包,其实上面例子就是一个闭包,我们无意间写了很多闭包,哈哈哈哈
foo = null
为什么会有内存泄漏