標籤:font size 電腦 1.5 ons console return 測試 全域
對於沒有接觸過閉包的初學者來說,很難見名知義馬上理解什麼是閉包。所以首先我們要明確一下什麼是閉包。我們先來看一下官方對於閉包的解釋:所謂“閉包”,指的是一個擁有許多變數和綁定了這些變數的環境的運算式(通常是一個函數),因而這些變數也是該運算式的一部分。看了這個官方的解釋,大家對於閉包理解了嗎?反正當我看到這個解釋的時候是一臉蒙逼,不知道這說的是些什麼鬼。因為看到這個解釋我很難把閉包和我平時在js中進行的一些操作聯絡到一起更談不上學會應用閉包了。可以說閉包是js中的一個痛點,難就難在它很抽象。雖然對這個官方的解釋我們做不到完全理解,但是我們卻可以從中獲得一個關鍵性資訊,那就是閉包通常情況下是一個函數。既然是函數那我們就先說一下由關於函數中變數的範圍問題。
1.變數的範圍
變數無非就分全域變數和局部變數兩種。
全域變數:在函數外部定義的變數叫全域變數;全域變數在函數內外都可以被訪問。
局部變數:在函數內部定義的變數叫局部變數;局部變數只在函數內部起作用,在函數外部存取不到。
下面我將用代碼示範一下全域變數和局部變數的區別。
<script type="text/javascript"> var num = 1; function first(){ alert(num); } first();//執行這個函數
alert(num);
</script>
num在函數外部聲明,所以是全域變數。這段代碼的運行結果是彈出兩次1;由此可見全域變數在函數內部是可以訪問到的。
<script type="text/javascript"> function first(){ var num = 1; } first(); alert(num);</script>
num在函數內部聲明,所以是局部變數。這段代碼的運行結果是報錯:num is not defined;由此可見局部變數在函數外部是訪問不到的。
2.如何在函數外部擷取函數內部的變數值
在很多情況下雖然是在函數內部定義的變數但是在函數外部我們仍然需要調用它,此時應該怎麼辦呢?我們可以通過下面的方式實現;
<script type="text/javascript"> function first(){ var num = 1; function func(){ alert(num); } return func; } var f1 = first(); //調用函數 console.log(f1); //列印f1</script>
列印的結果是:function fun(){alert(num)};也就是說此時的f1就是func函數。 要想彈出num的值我們可以將上述的f1改為:
var f1 = first();
f1();
此時啟動並執行結果會彈出num的值1; var f1 = first()時f1代表的是func函數,當 f1()的時候代表執行func函數,所以會彈出num的值。
那麼現在問題來了,我們為什麼要這麼做呢,首先我們都應該明白一個問題就是定義在函數內部的變數可以被它的子函數訪問,而不能在外部直接存取。所以我們需要通過func這個函數來獲得num值。
3.何謂閉包
上面講了那麼多,還沒有進入我們今天的主題——閉包。其實我們剛剛已經應用了閉包。上面的func函數就是閉包。是不是感覺有點神奇,不知不覺我們就用了js中的大痛點寫了個程式。我們可以把閉包簡單理解成"定義在一個函數內部的函數"。所以,在本質上,閉包就是將函數內部和函數外部串連起來的一座橋樑。
4.閉包的用途:
上面我們已經提到過了,閉包是將函數內部和函數外部串連起來的一座橋樑。所以它的一個用途就是可以在函數外部擷取函數內部的變數值,還有一個作用就是可以將變數存放在記憶體中;為了協助大家理解,我寫一個案例來說明:
var nu; function first(){ var num = 1; nu = function func1(){ num+=10; } function func(){ return num; } return func; } var f1 = first(); //調用first函數 var num1 = f1(); console.log(f1); console.log(num1); nu(); var num2 = f1(); console.log(num2);
我們一起來分析一下這次代碼的列印結果:
1.列印出的f1為function func(){return num},因為first函數的傳回值是func,所以f1為函數func;
2.列印出的num1的值是1。var num1 = f1();這行代碼的意思是說執行func函數。所以num1 = func函數的傳回值num(1);
3.列印出的num2的值是11。 nu()表示的是中間的func1函數的運行,注意我定義的nu是全域變數,如果將func1函數改為var nu = function func1(){num+=10;}直接寫nu()就會報錯了。
nu()執行完以後num = 11;此時再執行f1得到的數值是num2 = 11;
注意:使用閉包可以儲存變數的值,但是對於電腦來說也會造成負擔,所以使用閉包之前都要考慮好這些問題,不可過多使用閉包。
5.測試
通過上面的講解,相信大家對閉包都已經有了一定的瞭解,接下來讓我們用兩個小程式來檢驗一下自己的學習成果吧;
demo1:
var sex = "女"; var object = { sex : "男", func : function(){ return function(){ return this.name; }; } }; alert(object.func()());
demo2:
var sex = "女"; var object = { sex : "男", func : function(){ var that = this; return function(){ return that.sex; }; } }; alert(object.func()());
但是要完全搞懂這個代碼還需要瞭解this的用法,可參考http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html;
js中的閉包