什么是闭包?
概念闭包函数:声明在一个函数中的函数,叫做闭包函数。
闭包:闭包是一种代码形式,内部函数访问外部函数的局部变量。内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。
举例(面试题)::js函数A里面有一个函数B,函数B访问了函数A里面定义的局部变量,此时就产 生了闭包。变量所在的函数就是闭包函数,这里A就是闭包函数。
特点:
1. 让外部访问函数内部变量成为可能;
2.局部变量会常驻在内存中;
3.可以避免使用全局变量,防止全局变量污染;
4.会造成内存泄漏(有一块内存空间被长期占用,而不被释放)
闭包的创建:
闭包就是可以创建一个独立的环境,每个闭包里面的环境都是独立的,互不干扰。闭包会发生内存泄漏,每次外部函数执行的时 候,外部函数的引用地址不同,都会重新创建一个新的地址。但凡是当前活动对象中有被内部子集引用的数据,那么这个时候,这个数据不删除,保留一根指针给内部活动对象。
闭包内存泄漏为: key = value,key 被删除了 value 常驻内存中; 局部变量闭包升级版(中间引用的变量) => 自由变量;
实例
例1 闭包找到的是同一地址中父级函数中对应变量最终的值
// 外部函数
function outer() {
// 外部函数中的局部变量
let n = 10
// 内部函数
function inner() {
// 内部函数访问外部函数的局部变量
console.log(n);
}
//将内部函数return出去,这样外部才可以调用
return inner
}
let fn = outer();
console.log(fn);
fn()
例2:解决变量污染问题,让变量被函数保护起来。
// 示例代码
let count = 0
setInterval(function() {
console.log(count++);
}, 1000)
// 以上代码中的count是一个使用频率很高的变量名。
// 为了避免和其他位置的代码冲突, 可以再使用一个函数把以上的代码包裹起来, 起到保护作用。
function fn() {
let count = 0
setInterval(function() {
console.log(count++);
}, 1000)
}
fn()
// 以上代码中, setInterval函数与count构成了闭包
例3
function fn() {
let count = 0
function add() {
console.log(count++);
}
setInterval(add, 1000)
}
fn()
// 以上代码中, add + count构成了闭包
总结: 一个函数内使用了外部的变量, 那这个函数和被使用的外部变量一起被称为闭包结构。
在实际开发中,通常会再使用一个函数包裹住闭包结构,以起到对变量保护的作用。
例4 :可以延长变量的生命周期
变量的声明周期:
全局变量:从声明开始 直到 页面关闭
局部变量: 从声明开始 直到 函数执行结束
// 【全局变量】
// 全局变量n 写在函数外面
let n = 10;
function ck() {
console.log(n);
}
// 函数内部可以访问到全局变量
ck() // 10
// 【局部变量】
function outer() {
// 局部变量:特点1-只能在函数内部访问
// 特点2-函数执行结束后就会被销毁
let b = 20;
// 内部访问局部变量v
console.log(b); //20
};
outer(); //20
// 函数作用域外,访问局部变量x
console.log(b); // b is not defined
// 【将上述情况变成闭包函数,定义一个内部函数,让其访问到外部函数的局部变量】