1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        JS閉包的9大經(jīng)典使用場(chǎng)景

        共 5831字,需瀏覽 12分鐘

         ·

        2021-06-19 13:24

        作者:fly63

        http://www.fly63.com/article/detial/9974

        1.返回值(最常用)

        //1.返回值 最常用的
        function fn(){
            var name="hello";
            return function(){
                return name;
            }
        }
        var fnc = fn();
        console.log(fnc())//hello

        這個(gè)很好理解就是以閉包的形式將 name 返回。

        2.函數(shù)賦值

        var fn2;
        function fn(){
            var name="hello";
            //將函數(shù)賦值給fn2
            fn2 = function(){
                return name;
            }
        }
        fn()//要先執(zhí)行進(jìn)行賦值,
        console.log(fn2())//執(zhí)行輸出fn2

        在閉包里面給fn2函數(shù)設(shè)置值,閉包的形式把name屬性記憶下來(lái),執(zhí)行會(huì)輸出 hello。

        3.函數(shù)參數(shù)

        function fn(){
            var name="hello";
            return function callback(){
                return name;
            }
        }
        var fn1 = fn()//執(zhí)行函數(shù)將返回值(callback函數(shù))賦值給fn1,
         
        function fn2(f){
            //將函數(shù)作為參數(shù)傳入
            console.log(f());//執(zhí)行函數(shù),并輸出
        }
        fn2(fn1)//執(zhí)行輸出fn2

        用閉包返回一個(gè)函數(shù),把此函數(shù)作為另一個(gè)函數(shù)的參數(shù),在另一個(gè)函數(shù)里面執(zhí)行這個(gè)函數(shù),最終輸出 hello

        4.IIFE(自執(zhí)行函數(shù))

        (function(){
            var name="hello";
            var fn1= function(){
                return name;
            }
            //直接在自執(zhí)行函數(shù)里面調(diào)用fn2,將fn1作為參數(shù)傳入
            fn2(fn1);
        })()
        function fn2(f){
            //將函數(shù)作為參數(shù)傳入
            console.log(f());//執(zhí)行函數(shù),并輸出
        }

        直接在自執(zhí)行函數(shù)里面將封裝的函數(shù)fn1傳給fn2,作為參數(shù)調(diào)用同樣可以獲得結(jié)果 hello

        5.循環(huán)賦值

        //每秒執(zhí)行1次,分別輸出1-10
        for(var i=1;i<=10;i++){
            (function(j){
                //j來(lái)接收
                setTimeout(function(){
                    console.log(j);
                },j*1000);
            })(i)//i作為實(shí)參傳入
        }

        如果不采用閉包的話,會(huì)有不一樣的情況。

        6.getter和setter

        function fn(){
            var name='hello'
            setName=function(n){
                name = n;
            }
            getName=function(){
                return name;
            }

            //將setName,getName作為對(duì)象的屬性返回
            return {
                setName:setName,
                getName:getName
            }
        }
        var fn1 = fn();//返回對(duì)象,屬性setName和getName是兩個(gè)函數(shù)
        console.log(fn1.getName());//getter
        fn1.setName('world');//setter修改閉包里面的name
        console.log(fn1.getName());//getter

        第一次輸出 hello 用setter以后再輸出 world ,這樣做可以封裝成公共方法,防止不想暴露的屬性和函數(shù)暴露在外部。

        7.迭代器(執(zhí)行一次函數(shù)往下取一個(gè)值)

        var arr =['aa','bb','cc'];
        function incre(arr){
            var i=0;
            return function(){
                //這個(gè)函數(shù)每次被執(zhí)行都返回?cái)?shù)組arr中 i下標(biāo)對(duì)應(yīng)的元素
                 return arr[i++] || '數(shù)組值已經(jīng)遍歷完';
            }
        }
        var next = incre(arr);
        console.log(next());//aa
        console.log(next());//bb
        console.log(next());//cc
        console.log(next());//數(shù)組值已經(jīng)遍歷完

        8.首次區(qū)分(相同的參數(shù),函數(shù)不會(huì)重復(fù)執(zhí)行)

        var fn = (function(){
         var arr=[];//用來(lái)緩存的數(shù)組
         return function(val){
             if(arr.indexOf(val)==-1){//緩存中沒(méi)有則表示需要執(zhí)行
                 arr.push(val);//將參數(shù)push到緩存數(shù)組中
                 console.log('函數(shù)被執(zhí)行了',arr);
                 //這里寫想要執(zhí)行的函數(shù)
             }else{
                 console.log('此次函數(shù)不需要執(zhí)行');
             }
             console.log('函數(shù)調(diào)用完打印一下,方便查看已緩存的數(shù)組:',arr);
         }
        })();

        fn(10);
        fn(10);
        fn(1000);
        fn(200);
        fn(1000);

        執(zhí)行結(jié)果如下:
        可以明顯的看到首次執(zhí)行的會(huì)被存起來(lái),再次執(zhí)行直接取。

        9.緩存

        /比如求和操作,如果沒(méi)有緩存,每次調(diào)用都要重復(fù)計(jì)算,采用緩存已經(jīng)執(zhí)行過(guò)的去查找,查找到了就直接返回,不需要重新計(jì)算    
        var fn=(function(){
          var cache={};//緩存對(duì)象
          var calc=function(arr){//計(jì)算函數(shù)
              var sum=0;
              //求和
              for(var i=0;i<arr.length;i++){
                  sum+=arr[i];
              }
              return sum;
          }

          return function(){
              var args = Array.prototype.slice.call(arguments,0);//arguments轉(zhuǎn)換成數(shù)組
              var key=args.join(",");//將args用逗號(hào)連接成字符串
              var result , tSum = cache[key];
              if(tSum){//如果緩存有   
                  console.log('從緩存中?。?,cache)//打印方便查看
                  result = tSum;
              }else{
                  //重新計(jì)算,并存入緩存同時(shí)賦值給result
                  result = cache[key]=calc(args);
                  console.log('存入緩存:',cache)//打印方便查看
              }
              return result;
          }
        })();
        fn(1,2,3,4,5);
        fn(1,2,3,4,5);
        fn(1,2,3,4,5,6);
        fn(1,2,3,4,5,8);
        fn(1,2,3,4,5,6);

        輸出結(jié)果:

        瀏覽 52
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            无马人妻| 欧美老伦妇一区二区三区 | 国产免费三片 | 雷神吃旅行者萝卜视频 | xxxxwwww国产 | 精品秘 一区二三区在线男奴 | 吻胸摸腿娇喘揉屁股娇喘软件 | 女free性2ozc交 | 精品一区二区三区在线成人 | 浪妇粗口叫床对白 |