zoukankan      html  css  js  c++  java
  • 闭包理解大全相信你会更加理解闭包!!!

    文章后有彩蛋

    闭包概念:是指在JavaScript中,内部函数总是可以访问-其所在局部作用域中声明的参数和变量,即使在其所在局部作用域被销毁后,依然可以访问.

    闭包的原理:借助函数的立即执行、参数以及函数的return返回值,多创建了一层作用域。从而实现外部函数,持续性被引用而不能释放内存空间,将值存储下来。

    闭包函数:定义在局部作用域中的函数.

    闭包本质:将闭包函数外的局部变量常驻内存. (在程序中,避免使用全局变量,推荐使用私有,封装的局部变量)

    缺点:内存泄露(任何对象在你不在需要他之后仍然存在).

    解决方案:在退出函数之前,将不使用的局部变量全部删除。(面试的时候会问到哦)

    window.onload = function(){ var el = document.getElementById("id"); el.onclick = function(){ alert(el.id); } }

    window.onload = function(){ var el = document.getElementById("id"); var id = el.id; //解除循环引用 el.onclick = function(){ alert(id); } el = null; // 将闭包引用的外部函数中活动对象清除 }

    闭包的特性:1.函数内再嵌套函数; 2.内部函数可以引用外层的参数和变量;3.参数和变量不会被垃圾回收机制回收。

    以下1,2例题 是对概念的理解,其余都是一些练习,配合下一章的匿名函数自执行,希望你对闭包会有更深的理解:

    1.函数内部访问函数外部的数据
                var a = 1;           //全局变量
                function fn_01(){
                    alert(a);
                }
                fn_01();     //1
              
                function fn_02(){
                    var num = 10;
                }
                fn_02();
                alert(num);    //num is not defined 
                //外部想访问函数内部局部的私有变量,是不能直接访问到的
                //因为局部变量会在函数运行以后被销毁,这就用到了闭包。(闭包函数是可以访问到的)
                
    2.通过闭包访问局部变量
                function fn_01(){
                    var num = 3;           //变量
                    return function(){    //闭包函数
                        return num;
                    }
                }
                alert( fn_01()() );       //闭包函数访问局部作用域中的变量
                
                function fn_02(num){      //参数 var num 形式参数(形参):定义函数时接收数据的参数。 实际参数(实参):调用函数时传递的参数。
                    return function(){        //闭包函数
                        return num;
                    }
                }
                alert( fn_02(4)() );      //闭包函数访问局部作用域中的参数

    3.循环里的匿名函数的取值问题
                function fn_01(){
                    var arr = [];
                    for(var i = 0;i < 5;i++){
                        arr[i] = function(){    //函数没有执行,没有取外面i的值,只将函数块赋值给了数组arr
                            return i;        
                        }
                    }
                    return arr;
                }
                alert( fn_01() );  
    /*解释: 数组arr  循环5次都将function匿名函数存放在了数组中,函数并没有执行
                function(){
                    return i;
                },function(){
                    return i;
                },function(){
                    return i;
                },function(){
                    return i;
                },function(){
                    return i;
                }

    */
           //自己执行
                function fn_02(){
                    var arr = [];
                    for(var i = 0;i < 5;i++){
                        arr[i] = (function(){
                            return i;
                        })();            //让闭包函数自执行,每次执行,都将i存放在数组arr中
                    }
                    return arr;
                }
                alert( fn_02() );    //arr = [0,1,2,3,4];

      //传参数
                function fn_03(){
                    var arr = [];
                    for(var i = 0;i<5;i++){
                        arr[i] = (function(i){
                            return i;    
                        })(i)                 //函数执行,返回循环每一次i的值,作为参数,传递给闭包函数,返回值i,传递给数组
                    }
                    return arr;
                }
                //alert(fn_04());
                var list = fn_04();
                for(var j = 0,len = list.length;j < len;j++){
                    alert(list[j]);       //返回数组是[0,1,2,3,4]
                }
              //传参数加 闭包函数
               function fn_04(){
                    var arr = [];
                    for(var i = 0;i<5;i++){
                        arr[i] = (function(i){     //闭包函数
                            return function(){    //闭包函数    
                                return i;
                            };
                        })(i)              //函数执行,返回循环每一次i的值,作为参数,传递给闭包函数,返回值i,传递给数组
                    }
                    return arr;
                                        //此时arr数组存放的是function(){return i;}这个函数块  取值的时候,向上面的父级函数取i,这里的i传递的参数是循环变量每次的i
                }
                //alert(fn_04());
                var list = fn_04();
                for(var j = 0,len = list.length;j < len;j++){
                   alert(list[j]());   
                }
               
    练习题 1. fn(1)(2)(3)   使用闭包得到6
                function fn(x){
                    
                    return function(y){
                        
                        return function(z){
                            
                            alert(x+y+z);
                        }
                    }
                }
                fn(1)(2)(3);
    练习题 2.
                var name = "jack";
                var obj = {
                    name: "Lisa",
                    getName : function(){
                        return function(){     //闭包  
                            return this.name;
                        }
                    }
                }
                alert( obj.getName()() );   
                
                var name = "jack";
                var obj = {
                    name: "Lisa",
                    getName :function(){
                        var that = this;        //this 指向obj
                        return function(){
                            return that.name;
                        }
                    }                                                
                }
                alert( obj.getName()() );                                   
          
    练习题 3.三个数的累加,要求:同时支持下面两种写法
                //sum(1)(2)(3)  使用闭包得到6
                //sum(1,2,3);
                var sum = (...a)=>{  //a表示所有的参数
                    if(a.length == 3;){
                        return a[0] + a[1] + a[2];
                    }else{
                        var x = a[0];
                        return function(y){
                            return function(z){
                                return x + y + z;
                            }
                        }
                    }
                }
                alert( sum(1,2,3) );
                alert( sum(1)(2)(3) );
                
    练习题 4.点击按钮,让按钮里面的值++

    <style type="text/css">
     #btn{
           80px;
           height:30px;
           font-size: 16px;
     }
    </style>
     <input type="button" value="0" id="btn"/>

             var oBtn = document.getElementById("btn")
             oBtn.onclick = function(){
                    this.value = Number(this.value) + 1;
              }
                //闭包写法实现
                (function(){
                    var i = Number(oBtn.value);
                    oBtn.onclick = function(){
                        this.value = ++ i;
                    }
                })() //减少全局变量 

              function fn_06(){
                    var i = 0;
                    return function(){
                        return ++ i;
                    }
                }
                var n = fn_06();
                oBtn.onclick = function(){
                    this.value = n();
                }


                //循环加计时器--闭包解决   
                for (var i=1; i<=9; i++) {
                    setTimeout( function timer(){
                        console.log( i );
                    },1000 );
                }

        /*解释  i = 0  ...覆盖 1,2,3,4   
                  setTimeout(function(){console.log(i);},0)  //计时器,是延时操作,即使事件是0,也排在后面执行(异步)
                  setTimeout(function(){console.log(i);},0)
                  setTimeout(function(){console.log(i);},0)
                  setTimeout(function(){console.log(i);},0)
                  setTimeout(function(){console.log(i);},0)
                    最后 i = 5  不执行下面了,  所以输出5个5  */

      //闭包解决
                for (var i=1; i<=9; i++) {
                    (function(j){
                        setTimeout( function timer(){
                            console.log( j );
                        }, 1000 );
                    })( i );
                 }  

           //let 也可以解决(详解可以看前几章关于for循环中有关let的解释)

        for(let i = 0;i < 5;i ++){
                        setTimeout(function(){
                          console.log(i);
                       },0)        
                 }
              /*      i=0
                    setTimeout(function(){console.log(i);},0)
                    i=1
                    setTimeout(function(){console.log(i);},0)  .....i=2 i=3 i=4   */


    这是 一道面试题,如何更改下面的代码,将a[6] 输出的结果得到6 ?
                var a=[];
                for(var i=0;i<10;i++){
                    a.push(
                        function(){console.log(i)}
                    );
                }
                a[6]();  //10
                
                var a=[];
                for(let i=0;i<10;i++){
                    a.push(
                        function(){console.log(i)}
                    );
                }
                a[6](); // 6
                
                var a=[];
                for(var i=0;i<10;i++){
                    a.push(
                        function(i){
                            return function(){
                                console.log(i);
                            }
                        }(i)
                    );
                }
                a[6]();  //6

     彩蛋来啦!!!

    在js开始的地方会写一个分号   作用: 防止更多的js代码污染
    jQ代表的意思是:对象
    new 出来的是什么:对象,万物皆可new,万物皆对象
  • 相关阅读:
    BZOJ1293: [SCOI2009]生日礼物
    BZOJ2326: [HNOI2011]数学作业
    BZOJ1179: [Apio2009]Atm
    树链剖分的一个小细节
    BZOJ1146: [CTSC2008]网络管理Network
    BZOJ1984: 月下“毛景树”
    BZOJ3196: Tyvj 1730 二逼平衡树
    BZOJ1579: [Usaco2009 Feb]Revamping Trails 道路升级
    BZOJ1674: [Usaco2005]Part Acquisition
    Babel 在浏览器环境使用方法
  • 原文地址:https://www.cnblogs.com/lisaShare/p/8999981.html
Copyright © 2011-2022 走看看