js閉包和閉包範圍

來源:互聯網
上載者:User

先解釋一下什麼是閉包

閉包就是內建函式通過某種方式使其可見範圍超出了其定義的範圍,這就產生了一個在其定義範圍內的閉包.
我們先來瞭解一下內建函式(inner function)
javascript是支援內建函式申明(inner function declaration)的程式設計語言,

內建函式就是在另一個函數的內部定義,比如
function outerFun(){
  function innerFun(){
    alert('hello');
  }
}

函數innerFun就是內建函式, 它在函數outerFun範圍內是可見的,
也就是說innerFun函數的命名空間(namespace)是在outerFun範圍之內.

正確調用
function outerFun(){
  function innerFun(){
    alert('hello');
  }
  innerFun();
}
outerFun(); alerts hello
錯誤調用(error)
function outerFun(){
  function innerFun(){
    alert('hello');
  }
}
innerFun();

那麼如果我想在函數outerFun外面調用函數innerFun,我該如何做呢
做法1
var globVar;
function outerFun() {
  function innerFun() {
   alert('hello');
  }
  globVar = innerFun;
}
outerFun();
globVar();
做法2
function outerFun() {
  function innerFun() {
    alert('hello');
  }
  return innerFun ;
}
var globVar = outerFun();
globVar();

做法3
function outerFun() {
  function innerFun() {
    alert('hello');
  }
  return {'innerFun'innerFun} ;
}
var globVar = outerFun();
globVar.innerFun();

以上三種做法把內建函式的可見範圍擴大了, 其中最後一種做法是把內建函式當做匿名對象{'innerFun'innerFun}的屬性,並隨之一起返回.

從中看到在javascript裡面,函數名稱可以當作是一種引用變數,類似於c裡面指標的概念,在這裡,隨著程式的執行
會產生兩個引用變數指向內建函式innerFun,一個是globVar(第三種做法是globVar.innerFun),另一個是其函數自身innerFun,
只不過這兩個變數的可見範圍不一樣,即命名空間不一樣.
javascript記憶體回收行程會在函數最後一個引用變數被廢棄後,釋放其所佔用的記憶體.

再瞭解一下變數範圍
例1 內建函式變數
在內建函式內申明的變數其可見範圍就在其函數內
function outerFun() {
   function innerFun() {
      var innerVar = 0;
      innerVar++;
      alert(innerVar);
   }
   return innerFun;
}
var globVar = outerFun();
globVar();  Alerts 1
globVar();  Alerts 1
var innerVar2 = outerFun();
innerVar2();  Alerts 1
innerVar2();  Alerts 1

每一次內建函式調用,一個新的innerVar變數都被建立,所以結果顯示都是1


例2 內建函式引用全域變數(global variables)

var globVar = 0;
function outerFun() {
  function innerFun() {
    globVar++;
    alert(globVar);
  }
  return innerFun;
}
var globVar = outerFun();
globVar();  Alerts 1
globVar();  Alerts 2
var globVar2 = outerFun();
globVar2();  Alerts 3
globVar2();  Alerts 4
每一次內建函式的調用,全域變數都增加1,所以顯示結果都是依次遞增.

例3 內建函式引用外部函數變數
 
  function outerFun() {
     var outerVar = 0;
     function innerFun() {
       outerVar++;
       alert(outerVar);
     }
     return innerFun;
  }
 
  var globVar = outerFun();
  globVar();  Alerts 1
  globVar();  Alerts 2
  var globVar2 = outerFun();
  globVar2();  Alerts 1
  globVar2();  Alerts 2
  注意在第2次調用outerFun()的時候重新建立了一個新的變數outerVar,所以顯示結果是1,2,1,2

什麼是閉包(closures)呢, 就是內建函式通過某種方式使其可見範圍超出了其定義的範圍, 如上例3,globVar 就是函數outerFun()的一個閉包,
而閉包產生的時機就是這句代碼var globVar = outerFun(); 再看上例3,閉包globVar第一次調用之後,變數outerVar 值 1 還是在記憶體
中,沒有回收,因為閉包globVar第二次調用的時候其值已經遞增為2 ,只要globVar沒有被廢棄掉,則outerVar的值就會一直存在. 像outerVar
這樣的變數稱其為自由變數

看完這些我們再瞭解一下閉包與物件導向編程之間的聯絡
   看看下面的例子
   function outerFun() {
     var outerVar = 0;
     function innerFun() {
     outerVar++;
     alert(outerVar);
     }
     function innerFun2() {
       outerVar = outerVar + 2;
       alert(globVar);
     }
     return {'innerFun' innerFun, 'outerFun2' outerFun2};
   }

   var globVar = outerFun();
   globVar.innerFun();  Alerts 1
   globVar.innerFun2();  Alerts 3
   globVar.innerFun();  Alerts 4
   var globVar2 = outerFun();
   globVar2.innerFun();  Alerts 1
   globVar2.innerFun2();  Alerts 3
   globVar2.innerFun();  Alerts 4
  
   outerFun()可以看成是類,globVar,globVar2可以看成是兩個執行個體,執行個體變數就是outerVar,並且是private. 函數innerFun(),
   innerFun2()就是執行個體方法. 
  
   可能這還不是很清楚,在看下面的例子
   function Boy(){
      var name;
      function setName(vName){
        name = vName;
      }
      function getName(){
        return name;
      }
      return {'setName' setName, 'getName' getName};
   }
   var boy1 = Boy();
   boy1.setName(zhuzhenhua);
   alert(boy1.getName());


作者:zmyxmjz

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.