js-高級(閉包-遞歸)

1 閉包(closure)

  • 在函數(shù)的外部去訪問函數(shù)內(nèi)部的變量,這一種機(jī)制其實(shí)就是閉包
    ※※案例說明↓
var  a = 0;
   function f(){
      var b = 1;
      function  f1(){
          console.log(b++);
      }    
      return f1;    
  }
  var t = f();
  t();

chrome下輸出的結(jié)果:1
簡單分析:函數(shù)f1()本身是定義在f()函數(shù)內(nèi)部 但是f1()去訪問了f()里面的b的變量,此時其實(shí)就形成了一個閉包;

1.1如何才能構(gòu)成一個閉包
  1. 在函數(shù)的內(nèi)部定義函數(shù)
    2)函數(shù)內(nèi)部訪問它外部的變量(如同上面f1()要訪問f())
1.2 閉包的優(yōu)點(diǎn)
  • 延長變量的生命周期
    正常情況下一個函數(shù)的調(diào)用之后,它內(nèi)部定義的變量就會被刪除掉(被回收),但是使用閉包之后,它的生命周期就會得到延長
    ※※案例說明↓
var  a = 0;
   function f(){
      var b = 1;
      function  f1(){
          console.log(b++);
      }    
      return f1();    
  }
  var c = f();
  c();
  c();
  c();

chrome下輸出的結(jié)果:1,2,3

1.3 閉包的缺點(diǎn)

閉包-內(nèi)存泄漏
※※案例一↓

function  f(){
  var a = 10;
  function f1(){
    console.log(a);
  }
  return  f1;
}
var t = f();
t();

chrome下輸出的結(jié)果:10;
案例分析:


內(nèi)存泄漏.PNG

※※案例二↓

var a = [1,2,3,4];
function f(){
  a = [];
}
f();
console.log(a);

chrome輸出的結(jié)果為空數(shù)組
案例分析:
1)a的右邊是一個應(yīng)用數(shù)據(jù)類型,
2)會在一個堆區(qū)里面開辟一個新的空間,用來存放數(shù)組里面的值
3)函數(shù)里面a的右邊是一個新的數(shù)組(空的數(shù)組)從而開辟了一個新的數(shù)組,使其引用地址在此時發(fā)生了改變
4)但是此時函數(shù)外面的a此時任然保存在堆區(qū)里面

鼠標(biāo)點(diǎn)擊案例(-閉包)

案例-鼠標(biāo)點(diǎn)擊事件


鼠標(biāo)點(diǎn)擊出現(xiàn)索引值.PNG

方法一
1)通過額外的添加一個自定義屬性,來保存 i 的值


添加自定義屬性.PNG

方法二
2)使用閉包
閉包-立即執(zhí)行函數(shù).PNG

案例分析:
① : f=function(){}就是一個閉包結(jié)構(gòu);
② : 它是一個函數(shù),它定義在另一個函數(shù)的內(nèi)部
③ : 它訪問的不是自己的變量-index
④ : 當(dāng)中加入了一個立即執(zhí)行函數(shù)(移步?立即執(zhí)行函數(shù)章節(jié))
⑤ : 函數(shù)的返回值會保存在btns[i]這個對象中的onclick屬性中

遞歸

語法結(jié)構(gòu):
在函數(shù)的內(nèi)部調(diào)用自己(自己調(diào)用自己)
※※案例↓

function f(){
    console.log('f');
    f();
}
f();
````
chrome下的結(jié)果:陷入死循環(huán)(棧溢出)
######遞:
遞進(jìn) : 把大問題分成小問題,一層一層向我們知道的那個答案靠近
######歸:
回歸 : 小問題都已經(jīng)得到了解決,從最小的問題向最大的問題回歸,一個個解決

※※案例一 >求多為數(shù)組中的元素的個數(shù)↓
````
<script>
    var arr = [1,2,3,4,[56,45]];
    function count(arr){
        var sum = 0;
        for (var i = 0; i < arr.length; i++) {
            if(Array.isArray( arr[i] ) == false){
                sum +=1;
            }
            else{
                sum += count(arr[i]);
            }
        }
        return sum;
    }
    console.info( count(arr) ) ;
</script>
````
chrome下輸出結(jié)果:6
案例分析:
1)遞歸調(diào)用的函數(shù)。
2)Count()的功能是:你給我一個數(shù)組,我告訴你它有幾個元素。
3)如果數(shù)組中的元素就是一個普通的元素(非數(shù)組的)則sum++即可。
4)如果數(shù)組中的元素又是一個數(shù)組,則需要遞歸調(diào)用count(當(dāng)前元素)
※※案例二 >循環(huán)與遞歸↓
  ````
<script>
        //用循環(huán)來做
    function f1(n){
        var sum = 1;
        for (var i = 1; i <= n; i++) {
            sum *=i;
        }
        return sum;
    }
        //遞歸來做
    function f2(n){
        if(1== n){
            return 1;
        }
        else
            return f2(n-1) * n;
    }
        //算計(jì)時
    function computerTime(f,n){
        var t1 = new Date();
        var result = f(n);
        var t2 = new Date();
        console.info("時間:"+ (t2-t1) + "  結(jié)果: "+result);
    }
    computerTime(f1,10000);
    computerTime(f2,10000);
</script>
````
案例分析:
1) : 遞歸有最大的嵌套次數(shù)
2) : 可用用循環(huán)就不要用遞歸,一般來說,循環(huán)的效率比遞歸的效率更高一些
3) : 如果使用循環(huán)不能解決,再考慮用遞歸
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容