浅谈JS的闭包

什么是闭包?

官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

相信很少有人能直接看懂这句话,因为他描述的太学术。其实这句话通俗的来说就是:Javascript中所有的function都是一个闭包。不过一般来说,嵌套的function所产生的闭包更为强大,也是大部分时候我们所谓的“闭包”。看下面这段代码:

function a() { 
 var i = 0; 
 function b() { alert(++i); } 
 return b;
}
var c = a();
c();

这段代码有两个特点:
1、函数b嵌套在函数a内部;
2、函数a返回函数b
在执行完var c=a()后,变量c实际上是指向了函数b,再执行c()后就会弹出一个窗口显示i的值(第一次为1)。这段代码其实就创建了一个闭包,为什么?因为函数a外的变量c引用了函数a内的函数b,就是说:
当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。

产生闭包的条件:

函数嵌套
内部函数引用了外部函数的数据(变量/函数)

闭包的优点

(1)可以读取函数内部的变量。
变量的作用域无非就是两种:全局变量和局部变量;
S语言的特殊之处,就在于函数内部可以直接读取全局变量;
另一方面,函数外部自然无法读取函数内的局部变量。
(2)让这些变量的值始终保存在内存中,作用域空间不销毁,相对于局部变量来说,浪费了内存。
(3)保护私有变量

闭包的缺点:

常驻内存会增大内存的使用量
使用不当会造成内存泄露
闭包会在父函数外部,改变父函数内部变量的值

闭包的形成环境:

(1)函数的嵌套
(2)内部函数使用外部函数中的变量
(3)将内部函数返回,在外部函数的外部,接收返回值,执行(相当于执行了内部函数)

闭包的应用场景

(1)函数作为返回值。

function box() {
     var n = 1;  
     function cox() {
          n++;
          return n;
     }
     return cox;
}
// res 就是一个闭包 ,n像是一个全局变量
var res = box();
console.log(res()); // 2
console.log(res()); // 3

(2)循环中的事件,事件处理函数中使用了循环的每次的计数器。

<body>
    <div id="box"></div>
    <ul class="list">
        <li>link1</li>
        <li>link2</li>
    </ul>
</body>

<script>
var ali = document.querySelectorAll(".list li");
for(var i=0;i<ali.length;i++){
    ali[index].onclick = (function(index){
        return function(){
            console.log(index);
        }
   })(i);
}
</script>

(3)给某些系统默认的回调函数,传参。

function fn(a){
    return function(){
        console.log(a);
    };
}
setTimeout(fn("world"), 1000);

(4)处理掉全局变量。

var f = (function(){
    var a = "hello";
    function fn(){
        console.log(a + "world");
    }
    return fn;
})();
f();

Javascript的垃圾回收机制

在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。因为函数a被b引用,b又被a外的c引用,这就是为什么函数a执行后不会被回收的原因。

发布了22 篇原创文章 · 获赞 61 · 访问量 4012

猜你喜欢

转载自blog.csdn.net/zyfacd/article/details/104909401
今日推荐