1. 程式人生 > >小白都能看懂的閉包(closure)

小白都能看懂的閉包(closure)

前言:

閉包(closure)是Javascript語言的一個難點,也是它的特色,很多高階應用都要依靠閉包實現。

要理解閉包,首先必須理解Javascript特殊的變數作用域。

變數的作用域無非就是兩種:全域性變數和區域性變數。

Javascript語言的特殊之處,就在於函式內部可以直接讀取全域性變數。

 

1. 關於全域性變數 和 區域性變數的 理解:

函式外面: var a = 20; 此處var宣告的a是一個全域性變數

函式內部:function getAll() {

//如果是 var 宣告的,則是區域性變數 (與函式外面宣告的相反 )

var a = 20;

//如果是直接寫的(省去var宣告的),則是全域性變數

a = 20

}

 

訪問範圍:

全域性變數,在整個script中,都可以訪問到;

但是區域性變數只能在函式內部訪問到;函式外部是不能訪問到的。

有時候,想要在全域性訪問到函式內部的區域性變數,要怎麼辦?

——閉包,可以實現這一點。

 

2. 閉包(closure):

何為閉包?

在一個函式中寫入另外一個函式,並且可以訪問到這個函式的區域性變數的函式,這就是閉包。

在js中,只有一個函式內部的子函式才可以讀取區域性變數,所以,也可以把閉包理解為“定義在一個函式內部的函式”。

(本質上,閉包就是講函式內部和函式外部連結的一座橋樑。)

function fn1(){

var a = 20;

return function fn2(){

alert(a);

}

}

fn1()();

 

此處的 fn2函式就是閉包函式。

 

 

3. 閉包的作用:

第一:可以讀取一個函式內部的函式,

第二:避免“垃圾回收機制”回收,因為子函式會返回一個全域性變數,又會呼叫父函式的區域性變數,兩個變數相互呼叫;

所以,兩個函式都不會被清除。

 

4、關於閉包中this的指向問題( 進階版)。

 

程式碼一:

var name = 'The window ';

var object = {

name: ' my object',

fn1 : function(){

alert('1' + this.name); //此處this.name為 my object (因為會繼承object)

return function(){

alert('2' + this.name); //此處this.name為The window (沒有執行是上下文,所以,找到了windows )

return this.name;

}

}

}

object.fn1()();

 

難點:紅色部分打印出來的為什麼是“The window” ?

解釋:

我們可以換種寫法:

var obj = object.fn1()();

obj();

這裡的obj()是函式體 function() { return this.name };

此處的obj指向的是window,所以this.name是The.window

 

程式碼二:

var name = "The Window";

  var object = {

    name : "My Object",

    getNameFunc : function(){

        var that = this;

alert(that.name); //?

      return function(){

alert(this.name); //?

alert(that.name); //?

        return that.name;

      };

    }

  };

  object.getNameFunc()();

 

解釋:這裡只要是that.name都是指向的“My Object”;

因為,紅色的那行程式碼,把this的指向做了儲存。

但是如果用的是,this.name依然指向的是windows(可以參考程式碼一中的解釋)。