闭包:
形成闭包的条件:
- 1、函数嵌套函数(有作用域的嵌套)
- 2、内部函数使用了外部的变量/参数
作用:
- 内部函数使用的外部函数变量/参数会被永久的保存
例:
~function (){ //函数1
var num = 0; // 外部变量
document.onclick = function (){ // 函数2 函数嵌套函数
num ++; // 内部调用到外部变量
console.log( num )
}
}();
符合上面的条件:形成一个闭包 num 永久的保存
垃圾回收机制
+当所有环境都还在有对某个对象/数据的引用时,这个数据会被回收的
1、变量引用时:
var a = [ 1 , 2 , 3 ]
.
. 代码 中间这分部不会被回收
...
alert( a );
.
.没有对a再引用 这时候a就会被回收
.
...
2、函数引用时
function fn(){
var b = 0;
b++;
alert( b );
}
.
. 代码 fn里的 var b = 0 b++ alert( b ) 不会被回收
....
fn();
.
. 下面的代码没有对fn引用 fn里的函数体会 var b = 0 b++ alert( b ) 被回收掉
....
案例分析:
<script>
function fn(){
var a = 1;
return function (){
alert( ++a ) // 形成闭包 a不会被回收 永久的被保存
}
}
var fn2 = fn(); //fn执行 返回function (){ alert( a++ ) }
//a不会被回收 存在于 fn()这个作用域里
fn2(); //fn2()执行 弹出2 a = 2
fn2(); //fn2()执行 a就是上面 2 ; a++ 弹出3
</script>
<script>
function fn(){
var a = 0;
return function (){ //形成闭包
a++;
console.log( a );
}
}
var fn2 = fn(); //返回是function (){ a++ ; console.log( a ) }
var fn3 = fn(); //返回是function (){ a++ ; console.log( a ) } 这2个a是完全不一样的 只是长得一样而已
fn2(); //fn2()执行 产生一个新的作用域 a++ 弹出 2 这里的a会存放在fn2()这个作用域里
fn2(); //fn2() 再 a ++ 上面a已经是2 弹出3
fn3(); // fn3() 执行 产生一个新的作用域 a++ 弹出 2 这里的a会存放在fn3()这个作用域里
</script>
<script>
function fn( ) {
var a = 1;
fn2( a ); //这里没有形成闭包 都没有函数嵌套函数
}
function fn2( a ) {
a++;
alert( a );
}
fn();
</script>
闭包的优缺点:
- 闭包的优点就是缺点
使用的变量会被永久存储(只有关闭页面时才会被释放),我们可以对同一个变量重复利用
<script>
function fn(){
var num = 0; //我们记录点了多少次时
// 如果不用闭包就要在顶层下声明一个变量 用来记录 在全局声明会对顶层有污染
return function ( ) {
num ++;
console.log( num );
}
}
document.onclick = fn();
</script>
缺点
- 使用变量会被永久保存,当大量使用闭包时,会对内存的消耗有点点高