文章已同步至掘金: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能访问它们的:
- 参数
- 局部变量或函数
- 外部变量
如果在一个函数中,又嵌套了一个函数,并且里面这个函数引用外面的函数的变量,那么就是闭包。
闭包的特点:
- 闭包可以产生内存泄露
- 闭包可以延长变量的生命周期
评论区