初识JavaScript闭包

作者: 朋友喜欢叫我春哥 | 来源:发表于2017-04-02 12:05 被阅读84次

    前言:

    学习JavaScript的时候老是听说闭包,感觉他很厉害的样子,所以就来会会他吧!

    闭包

    闭包是什么?

    闭包是指有权访问另外一个函数作用域里的变量和参数的函数

    闭包的特点以及优缺点

    特点

    1. 函数嵌套函数
    2. 函数内部可以引用外部的参数和变量
    3. 参数和变量不会被垃圾回收机制回收

    一般函数执行结束后,局部变量会被销毁(垃圾回收机制所回收),内存只会保存全局作用域的变量。

    但是闭包就不同了,闭包会使变量继续保存在内存里,当然如果使用不当会增大内存使用量。

    function aaa() {  
      var a = 1;  
      return function(){
          alert(a++)
        };  
    }         
    var fun = aaa();  
    fun();// 1 执行后 a++,,然后a还在~  
    fun();// 2   
    fun = null;//a被回收!!
    

    优点

    1. 希望一个变量长期驻扎在内存中
    2. 避免全局变量的污染
    3. 私有成员的存在

    缺点

    闭包的缺点就是常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。

    循环中的闭包

    一个常见错误是在循环中使用变量,我们看个例子:

    function count() {
        var arr = [];
        for (var i=1; i<=3; i++) {
            arr.push(function () {
                return i * i;
            });
        }
        return arr;
    }
    
    var results = count();
    var f1 = results[0];
    var f2 = results[1];
    var f3 = results[2];
    

    你可能认为调用f1(),f2()和f3()结果应该是149,但实际结果是:

    f1(); // 16
    f2(); // 16
    f3(); // 16
    

    原因很简单,当你执行返回的函数时,闭包继续保持对变量i的访问,此时for循环已经结束并且i = 4,所以结果都是16。

    为了得到想要的结果,需要在每次循环中创建变量 i 的拷贝。为此我们一般采用自执行匿名函数

    function count() {
        var arr = [];
        for (var i=1; i<=3; i++) {
            arr.push((function (n) {
                return function () {
                    return n * n;
                }
            })(i));
        }
        return arr;
    }
    
    var results = count();
    var f1 = results[0];
    var f2 = results[1];
    var f3 = results[2];
    
    f1(); // 1
    f2(); // 4
    f3(); // 9
    

    自执行匿名函数

    创建一个自执行匿名函数

    (function (x) {
        return x * x;
    })(3); // 9
    
    //另外一种写法
    (function (x) { return x * x }) (3);
    

    总结

    很多初学者学了闭包后,可能也不懂到底在哪里才有用到,甚至不懂闭包到底有啥用。其实你写的每一个js函数都是闭包,一个js函数的顶层作用域就是window对象,js的执行环境本身就是一个scope(浏览器的window/node的global),我们通常称之为全局作用域。每个函数,不论多深,都可以认为是全局scope的子作用域,可以理解为闭包。

    闭包的概念其实是针对作用域而言的,闭包的当前作用域总是能够访问外部作用域中的变量,因为 函数 是 JavaScript 中唯一拥有自身作用域的结构,因此闭包的创建依赖于函数。

    文笔有限,才疏学浅,文中若有不对之处,还望告知。


    参考文章

    详解js闭包

    JavaScript 秘密花园

    廖雪峰JavaScript教程-闭包

    相关文章

      网友评论

        本文标题:初识JavaScript闭包

        本文链接:https://www.haomeiwen.com/subject/ihkgottx.html