javascript閉包的理解和執行個體

來源:互聯網
上載者:User

標籤:html   開發   引入   ret   文法   exe   檔案   括弧   script   

所謂閉包,值得是詞法表示包括不必要計算的變數的函數,也就是說,該函數可以使用函數外定義的變數。

順便提示一下:

詞法範圍:變數的範圍是在定義時決定而不是執行時決定,也就是說詞法範圍取決於源碼,通過靜態分析就能確定,因此詞法範圍也叫做靜態範圍。 with和eval除外,所以只能說JS的範圍機制非常接近詞法範圍(Lexical scope)。

 

下面是一個簡單的使用全域變數的閉包執行個體:

1 var sWord="Hello,Welcome to web前端開發工程師的部落格,請多多指教。"
2 function disWord(){
3     alert(sWord);
4 }
5 disWord();

解析:指令碼載入到記憶體的時候,disWord並沒有計算sWord的值,而是函數disWord調用的時候執行了sWord的計算。

下面是函數中定義另一個函數的閉包執行個體:

1 var iNum=10;
2 function add(num1,num2){
3     function doAdd(){return num1+num2+iNum;}
4     return doAdd();
5 }

解析:內建函式doAdd是個閉包,它將擷取傳入參數num1,num2和全域變數iNum的值,doAdd不接受參數,add最後一步調用doAdd,請兩個參數和全域變數求和返回,可以看得出doAdd使用的值是在執行環境中獲得的。

 

下面是在網上找的幾個例子,理解詞法範圍和閉包

 

1、案例一1  /*全域(window)域下的一段代碼*/
2 function a(i) {
3     var i;
4     alert(i);
5 };
6 a(10); 

 

疑問:上面的代碼會輸出什麼呢?
答案:10。

具體執行過程

  1. a 函數有一個形參 i,調用 a 函數時傳入實參 10,形參 i=10
  2. 接著定義一個同名的局部變數 i,未賦值
  3. alert 輸出 10

思考:局部變數 i 和形參 i 是同一個儲存空間嗎?

 

2、案例二 1  /*全域(window)域下的一段代碼*/
 2 function a(i) {
 3     alert(i);
 4     alert(arguments[0]); //arguments[0]應該就是形參 i
 5     var i = 2;
 6     alert(i);
 7     alert(arguments[0]);
 8 };
 9 a(10); 

疑問:上面的代碼又會輸出什麼呢?
答案:10,10,2,2

具體執行過程

  1. 函數有一個形參i,調用 a 函數時傳入實參 10,形參 i=10
  2. 第一個 alert 把形參 i 的值 10 輸出
  3. 第二個 alert 把 arguments[0] 輸出,應該也是 i
  4. 接著定義個局部變數 i 並賦值為2,這時候局部變數 i=2
  5. 第三個 alert 就把局部變數 i 的值 2 輸出
  6. 第四個alert再次把 argumentsa[0] 輸出

思考:這裡能說明局部變數 i 和形參 i 的值相同嗎? 

 

3、案例三1 /*全域(window)域下的一段代碼*/
2 function a(i) {
3     var i = i;
4     alert(i);
5 };
6 a(10)

疑問:上面的代碼又又會輸出什麼呢?
答案:10

具體執行過程

  1. 第一句聲明一個與形參 i 同名的局部變數 i,根據結果我們知道,後一個 i 是指向了
  2. 形參 i,所以這裡就等於把形參 i 的值 10 賦了局部變數 i
  3. 第二個 alert 當然就輸出 10

思考:結合案列二,這裡基本能說明局部變數 i 和形參 i 指向了同一個儲存地址!

4、案例四1 /*全域(window)域下的一段代碼*/
2 var i=10;
3 function a() {
4     alert(i);
5     var i = 2;
6     alert(i);
7 };
8 a(); 

疑問:上面的代碼又會輸出什麼呢?
答案:undefined, 2

具體執行過程

  1. 第一個alert輸出undefined
  2. 第二個alert輸出 2

思考:到底怎麼回事兒?

看到上面的幾個例子,你可能會想到底是怎麼執行的呢?執行的細節又是怎麼樣的呢? JS 引擎的工作方式是怎樣的呢?

解析過程

1、執行順序

     編譯型語言,編譯步驟分為:詞法分析、文法分析、語義檢查、代碼最佳化和位元組產生。 

    解釋型語言,通過詞法分析和文法分析得到文法分析樹後,就可以開始解釋執行了。這裡是一個簡單原始的關於解析過程的原理,僅作為參考,詳細的解析過程(各種JS引擎還有不同)還需要更深一步的研究

    javascript的執行過程,如果一個文檔流中包含多個script程式碼片段(用script標籤分隔的js代碼或引入的js檔案),它們的運行順序是:

  1. 步驟1. 讀入第一個程式碼片段(js執行引擎並非一行一行地執行程式,而是一段一段地分析執行的)
  2. 步驟2. 做詞法分析和文法分析,有錯則報語法錯誤(比如括弧不匹配等),並跳轉到步驟5
  3. 步驟3. 對【var】變數和【function】定義做“預解析“(永遠不會報錯的,因為只解析正確的聲明)
  4. 步驟4. 執行程式碼片段,有錯則報錯(比如變數未定義)
  5. 步驟5. 如果還有下一個程式碼片段,則讀入下一個程式碼片段,重複步驟2
  6. 步驟6. 結束

2、特殊說明
    全域域(window)域下所有JS代碼可以被看成是一個“匿名方法“,它會被自動執行,而此“匿名方法“內的其它方法則是在被顯示調用的時候才被執行
3、關鍵步驟
    上面的過程,我們主要是分成兩個階段

  1. 解析:就是通過文法分析和預解析構造合法的文法分析樹。
  2. 執行:執行具體的某個function,JS引擎在執行每個函數執行個體時,都會建立一個執行環境(ExecutionContext)和使用中的物件(activeObject)(它們屬於宿主對象,與函數執行個體的生命週期保持一致)

 在這裡有更詳細的執行個體分析資料:http://www.alixixi.com/web/a/2010062560089.shtml

 

javascript閉包的理解和執行個體

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.