DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> JavaScript基礎知識 >> 關於閉包的理解(JS學習小結)
關於閉包的理解(JS學習小結)
編輯:JavaScript基礎知識     

前言:

啊啊啊,看書真的很痛苦啊,還是好想做項目寫代碼才有意思,不過我現在缺的確是將知識體系化,所以不論看書多麼痛苦都一定要堅持堅持啊,這才是我現在最需要的進步的地方,加油!

因為現在期末啦,下周一也就是明天開始就有考試,所以復習是主要的事情,看書的速度比較慢了,一周大概也就184頁(P110-P284), 雖然頁數比較少但是其中有ES中非常最重要的兩個概念——原型鏈閉包,之前對於兩個知識的了解算是知其然不知其所以然的,所以在那兩章我也有意多花費了時間,確保我能夠吃透這個概念。以下算是我自己的一些理解,如果有不很正確的地方,希望大神們多多指教,康桑阿米達~

哦,對了,我看的JS書是《Javascript 高級程序設計(第3版)》,如果有正在看這本書的小伙伴可以一起哇~大家多多交流,互相學習嘛~

 

正文:

現在最流行的編程語言裡面一定有“對象”的概念,我們的第一節實驗課老師就叫我們怎麼找對象,所以可見對象對於程序猿的重要性,所以你有對象了嘛?:) 那這世界上對象千千萬,我們怎麼知道哪個對象合適呢?總不能一個一個的相處試試看吧?好在我們發現很多對象都有相似之處,所以我們將他們相似的部分抽象出來,形成了一個全新的概念,在我們需要的時候,比對我們的需要和這個概念,再進行選擇,就會節省我們很多功夫並更好更快的獲得我們想要的結果。而這個概念在JS中就是引用類型,Object(JS中沒有類的概念,如果學過C++或者Java、C#等語言的,那也會很容易就對應get到JS中引用類型的)。Object確實是JS中非常強大的部分,但卻不是最有意思的,那最有意思的是什麼?Function。

在JS中,Function也是一個Object的一個對象。而關於這個概念的延伸,像是繼承、原型鏈等等就又可以再開一把了,如果實在是饑渴難耐的,那就快去搜索大神們博客或者找一本《JavaScript高級程序設計》和我一起學習啦~所以,我們現在就將矛頭對准,閉包!開火,嘣嘣嘣嘣

在說閉包的概念之前,我們總得知道這個名詞到底是什麼意思吧?

所以什麼是閉包?函數。

既然就是函數為什麼又特別要取個名字?它到底特別在哪?

能夠訪問另一個函數作用域中的變量。(此處的作用域姑且理解為{}之內)

For example,上個例子就知道了,不要問我例子是誰

function outerFunc(arg){

   return function innerFunc(){
        alert(arg);
    }  

}

此處名為outerFunc的函數返回了一個名為innerFunc函數,這個函數在內部只有一句“alert(arg);”,可是運用技能一眼看穿法,找不到arg,再往上,哇哦,在outerFunc的參數那找到了呢,真開心。所以這個innerFunc(函數)訪問了outerFunc(另一個函數)作用域內(在outerFunc的{}中,但沒在innerFunc的{}中)的變量(arg),所以這個innerFunc就是一個閉包。(大多數時候,不會為閉包命名,此處只為更好的說明。)

OK,閉包的概念知道啦,那如何形成閉包這個現象的呢?顯然剛剛別有深意,欲拒還迎的作用域使的小把戲啦,別怕,我們立馬拿下。

“當某個函數被調用時,會創建一個執行環境及相應的作用域鏈。”

“每個執行環境都有一個表示變量的對象——變量對象。(variable object)。”

當然還是要先名詞解釋,要是都不知道這個名詞指的什麼,那還怎麼玩。

作用域:也就是變量對象的別稱。

作用域鏈:就是作用域呗。一條把作用域像臘肉穿起來的子。它只是一條鏈子所以作用域鏈就只保存著變量對象的地址,而不是變量對象本身。

執行環境執行環境指向自己獨有的作用域鏈作用域鏈又按照當前函數作用域,外部函數作用域,外部函數的外部函數作用域....直至全局作用域。

再來了解了解,我們寫了個函數然後調用它實現了功能,那JS到底又為此做了什麼。 (1)在創建函數時,會創建一個預先包含全局變量對象的作用域鏈,保存在內部的屬性[[scope]]中。 (2)當調用函數時,會為函數創建一個執行環境,然後通過復制函數的[[scope]]屬性,構建起執行環境的作用域鏈。 (3)創建一個活動對象(此處即變量對象)放在執行環境作用域鏈的最前端。 而當函數在訪問一個變量的時候,即在innerFunc函數的執行環境中執行到“alert(arg);”時,執行環境找到自己的作用域鏈小伙伴,然後作用域鏈說沒問題,我幫你問問我的作用域兄弟們,然後作用域鏈就問innerFunc()作用域,“你好,請問你有arg這個變量嗎?”“不好意思,我沒有呢。”“沒關系哦。謝謝你。”“不客氣。”(老師教導我們要做一個有禮貌的好孩子。)然後它又問outerFunc()作用域,“請問你有arg這個變量嗎?”“我有哦。”ok,皆大歡喜,找到了arg,順利執行了“alert(arg);”語句,否則一直到全局作用域依然沒有找到的話,就只能報錯了呢。 一般講,函數執行完畢,那就銷毀吧。但是,閉包就這麼被銷毀了,哪裡對得起它特別的名字呢?
 function outerFunc(arg){
 
    return function innerFunc(){
         alert(arg);
     }  
 
 }
 
 var result = outerFunc(1); //返回innerFunc函數
 result();                  //輸出1

 

還是剛才的函數,還是原來的配方,再加點料,看看效果。

按照剛剛說的,outerFunc在第9行執行完畢後,應該就被銷毀了(事實上也是如此),但為何第10行的執行依然能夠成功呢?聰明的你一定知道啦,作用域和作用域鏈的關系。outerFunc在第9行執行後,outerFunc的執行環境和作用域鏈都被銷毀,但是!innerFunc的作用域鏈還在對innerFunc作用域和outerFunc作用域進行引用。也就是所謂了“引用計數不唯一”。所以,盡管outerFunc已經被銷毀,但是innerFunc依然能夠訪問到arg變量的值啦。 所以你看閉包並沒有很難嘛,不用怕它,當然我在此說的,都是簡單的初級概念,閉包的運用就像是css中的浮動的運用一樣,知道概念是很容易的事情,但是真的運用得心應手確實是非常高段位的事了,所以一起加油咯~   後話: 明天考試英語,希望能考好啊,我要求不高,上90就行啊。(強行裝逼,不必理我)
XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved