js 闭包篇

JS闭包

相关要点

  1. 内存泄漏

    过多的占用系统内存的行为,相当于攥着一团湿毛巾,流失的水越多,剩余的水越少,相当于内存剩余越少。

  2. 何为功能

    一个真正的功能不应该依赖于外部的东西,自己本身就应该能独立完成这个事儿,这样的功能才是一个真正完整的功能。

    例:

    //一个简易累加器
    var count = 0;
    function test(){
        count ++;
        console.log(count);
    }
    test();
    test();
    test();
    
    //输出
    1
    2
    3
    
    //该功能依赖于外部的全局变量,并非自身完成,闭包的方法见下
    
  3. 只有表达式才能被执行

闭包理解

  • 当内部函数被保存到外部时将会产生闭包,闭包会导致原有作用域链不被释放(因为闭包函数拿着外部函数的执行成果,导致外部函数作用域链无法释放),造成内存泄漏。

  • 内部函数保存到外部函数的俩个简单方法( 还有更牛批的, but菜鸟的我还不会 ):

    1. return

      <script>
              function a() {
                  function b() {
                      console.log(tt);
                  }
                  var tt = 9;
                  return b;
              }
              var demo = a();
              demo();
      </script>
      
    2. 传值给全局变量

      <script>
          var demo
              function a() {
                  var tt = 9;
                  function b() {
                      console.log(tt);
                  }
                 demo = b;
              }
              a();
              demo();
      </script>
      
  • 闭包的特点:

    1. 闭包函数里能访问到其外部函数的局部变量
    2. 闭包函数能延长其外部局部变量的生命周期, 使其一直存在
    3. 模块化开发时,不会互相污染变量
    4. 当多个函数同时和一个函数形成闭包时,他们的变量是可以共用的,因为同属于一个域,类似缓存结构,例如闭包用法的例子

闭包的一些用法

  • 实现公有变量

    //函数累加器
    <script>
        function add() {
        var num = 0;
        function scr() {
            console.log(++num);
        }
        return scr;
    }
    var demo = add();
    demo();
    </script>
    
  • 可以做类似缓存的事情 (存储结构)

    <script>
        function test() {
        var ani = "dog";
        var obj = {
          terani : function () {
                if(ani != ""){
                    console.log("this is " + ani);
                    ani = "";
                }else{
                    console.log("empty!");
                }
            },
            pushani : function (newani) {
                ani = newani;
            }
        }
        return obj;
    }
    var animation = test();
    animation.terani();
    animation.terani();
    animation.pushani("lion");
    animation.terani();
    </script>
    
    //输出结果
    this is dog
    empty!
    this is lion
    
  • 可以实现封装,属性私有化

  • 模块化开发,防止污染全局变量

闭包编程常见坑

  • 函数的执行顺序并非视觉上的顺序,函数只有在调用时才执行,在它未执行时,函数中的值是随着执行语句前的行为在变的。

    //简单例子
    num = 100;
    function test(){
        console.log(num);
    }
    num = 200;
    test();
    
    //输出
    num = 200;
    
    //复杂例子
    function test() {
        var arr = [];
        for (var i = 0; i < 10; i++) {
            arr[i] = function () {
                console.log(i);
            }
        }
        return arr;
    }
    var myarr = test();
    for (var j = 0; j < 10; j++) {
        myarr[j]();
    }
    //输出
    1010
    //解决这个问题,让他正常输出
    //利用立即执行函数,形成1对1的形式
     function test() {
                var arr = [];
                for (var i = 0; i < 10; i++) {
    
                  (function (j) {
                    arr[j] = function () {
                        console.log(j);
                    }
                  } (i))
    
                }
                return arr;
            }
            var myarr = test();
            for (var j = 0; j < 10; j++) {
                myarr[j]();
            }
    

闭包面试坑

  • 使用原生js,addEventListener,给每个li元素绑定一个click事件,输出他们的顺序

    <ul>
        <li>a</li>
        <li>a</li>
        <li>a</li>
        <li>a</li>
    </ul>
    

    错误写法:

    //闭包问题,导致输出全为4
    function test() {
        var liCollection = document.getElementsByTagName("li");
        for (var i = 0; i < liCollection.length; i++){
            liCollection[i].onclick = function () {
                console.log(i);
            }
        }
    };
    test();
    

    正确写法:

    //使用立即执行函数,形成一对一的形式
    function test() {
        var liCollection = document.getElementsByTagName("li");
        for (var i = 0; i < liCollection.length; i++){
    
            (function (j) {
                liCollection[j].onclick = function () {
                    console.log(j);
                }
            }(i))    
        }
    };
    test();
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值