不管你是学习JavaScript还是其他编程语言可能都对闭包这个概念有所理解,今天给大家分享的是在JavaScript中我对闭包的理解以及一些实例和闭包的作用
闭包的概念
在了解闭包之前你需要了解一些和它有关的概念如 : 作用域 , 作用域链 , 执行上下文
有关这一部分内容在我前面的一篇文章有提到过 JavaScript理解作用域
下面我们创建两个最简单的闭包 大家通过他的输出来看看能否理解
function fun(){
var n=666;
function bb(){
console.log(n);
}
return bb;
}
var result=fun();
result();
上面 **result()**函数输出的结果是 666 ,
在 Javascript 中,只有函数内部的子函数才能读取局部变量,所以这就是我们上面所说的闭包的实质就是在一个函数中定义的另一个有权访问变量的函数 好我们现在接着看下面这个例子
function fun1(){
var arr = [];
for(var i = 0; i < 3;i++){
arr[i] = function (){
console.log(i);
}
}
return arr;
}
var myArr = fun1();
myArr[0]();
myArr[1]();
myArr[2]();
这段代码输出的值为 3 3 3 而我们的 myArr就是闭包 当 myArr 被赋值为 fun1()时 执行里面的循环但我们并没有调用到arr函数所以 i 一直被累加到了 3 当我们进行 myArr[0](); 时则相当于在外部调用了到了 fun1 的return返回值即内部 arr函数 的变量打印了 i 而此时的 i 以及被累加到了 3(闭包只能取得包含函数中任何变量的最后一个值,这是因为闭包所保存的是整个变量对象,而不是某个特殊的变量。) 所以后面的同理输出都为3
所以通过这两个例子我们可以再通俗一点理解闭包这里我看到一个很好的比喻
1. 闭包就是指一个变量在他自身作用域外被使用了,就叫发生了闭包或者说让我们有权访问另一个函数作用域中的变量的函数
2. 当一个函数被创建并传递或从另一个函数返回时,它会携带一个背包。背包中是函数声明时作用域内的所有变量, 这个背包是一个函数也就是闭包!
这两句话就是对闭包的理解
闭包的作用
- 延长变量的生命周期
var fun2 = function(){
var a = 1;
return function(){
a++;
console.log(a);
}
};
var bb = fun2();
我们知道JavaScript具有垃圾回收机制 当一个函数退出时这些局部变量就会被回收 但是我们可以放下上面代码不管你执行多少次 bb 都会一直输出累加的 a 值
- 封闭变量
我们上面那个输出结果是 333 的代码就是很好的例子 那我们如果想要他正常的顺序输出怎么做呢? 我们可以给 arr【i】外面包裹一个匿名即时执行函数 这样每循环一次都会立马执行一次输出
- 模拟面向对象
var f = function(){
var value = 0;
return {
bb:function(){
value++;
console.log(value);
}
}
};
var f = f();
这样我们一直操作 f.bb() 就可以一直累加输出属性value
闭包的弊端
由于闭包会使得函数中的变量都被保存在内存中不会被垃圾回收机制清除 , 所以会增大内存的使用量甚至导致内存泄漏 。 所以在不必要的时候尽量不要在函数中创建闭包函数 或者在一些变量使用完后 手动给它赋值 null 避免浏览器崩溃
另外闭包会在父函数外部,改变父函数内部变量的值。所以,当你把父函数当作object使用,把闭包当作它的公用方法,把内部变量当作它的私有属性),这时不要随便改变父函数内部变量的值。 避免造成变量污染。
如有错误,请指正