文章已同步至掘金:https://juejin.cn/post/6844903930082623496
欢迎访问😃,有任何问题都可留言评论哦~
什么是闭包?
闭包就是能够读取其他函数内部变量的函数。
例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成"定义在一个函数内部的函数"。
在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
代码演示:
当function
里嵌套function
时,内部的function
可以访问外部function
里的变量
function fn(x) {
var tmp = 3;
function bar(y) {
alert(x + y + (++tmp));
}
bar(2);
}
fn(1)
不管执行多少次,都会alert 7
,因为bar
能访问fn
的参数x
,也能访问fn
的变量tmp
。
但是,这并 不是 不是 不是 闭包
当你return
的是内部function
时,才是闭包
内部function
会close-over
外部function
的变量直到内部function
结束。
function fn(x) {
var tmp = 3;
return function (y) {
alert(x + y + (++tmp));
}
}
var bar = fn(1); // bar 现在是一个闭包
bar(2);
上面的脚本最终也会输出alert 7
,因为虽然bar
不直接处于fn
的内部作用域,但bar
还是能访问x
和tmp
。
但是,由于tmp
仍存在与bar
闭包的内部,所以它还是会自加1,而且你每次调用bar
时它都会自加1。
其实,我们其实可以建立不止一个闭包方法,比如return
它们的数组,也可以把它们设置为全局变量。它们全都指向相同的x
和相同的tmp
,而不是各自有一份副本。
一个需要关注的点:
JS里处理object
时是用到引用传递的,那么,你调用fn
时传递一个object
,fn
函数return
的闭包也会引用最初那个object
?
function fn(x) {
var tmp = 3;
return function (y) {
alert(x + y + tmp);
x.memb = x.memb ? x.memb + 1 : 1;
alert(x.memb);
}
}
var tar = new Number(1);
var bar = fn(tar); // bar 现在是一个引用了tar的闭包
bar(2);
不出我们意料,每次运行bar(2)
,x.memb
都会自加1。但需要注意的是x
每次都指向同一个object
变量tar
。
这样内存泄漏有关。
有一个不用return
关键字的闭包例子:
function closureExample(obj, text, timedelay) {
setTimeout(function() {
document.getElementById(objID).innerHTML = text;
}, timedelay);
}
closureExample('myDiv', 'Closure is created', 500);
总结:
JS里的function
能访问它们的:
- 参数
- 局部变量或函数
- 外部变量
如果在一个函数中,又嵌套了一个函数,并且里面这个函数引用外面的函数的变量,那么就是闭包。
闭包的特点:
- 闭包可以产生内存泄露
- 闭包可以延长变量的生命周期