不論是閉包仍是this關鍵字,都是困擾JS初學者的比較難懂的東西,若是你對它們的認識還不足夠清晰,那麼如今就一塊兒把它們掌握掉。仍是那句話,咱們從最基本的開始,創建起一個很是清晰的知識結構,好了,開始吧 ?javascript
固然咱們今天說的是javascript裏的閉包。要學習閉包,首先須要明白函數和變量,其次要知道變量和函數的一些特性。來複習一下:java
變量是那些會變化的東西(就這麼簡單),變量有一個值,咱們能改變這個值。咱們先聲明一個變量名,而後對這個變量賦值,就建立了一個變量。變量分按做用域(這個很重要後面會講到)爲全局變量和局部變量。閉包
咱們最初學習的是經過函數聲明來建立一個函數,即首先是 function 關鍵字,而後是函數的名字,這就是指定函數名的方式。另外一個方式叫作函數表達式,最多見的形式是這樣的:函數
var functionName = function(arg0, arg1, arg2){ //函數體 };
咱們建立的這個函數叫作匿名函數,由於 function 關鍵字後面沒有標識符,沒有名字嘛。
結合函數和做用域,咱們來小小地總結一下:函數內能夠讀取函數外的變量,而函數外卻讀取不了函數內部的變量(局部變量)。理解了這句話,咱們就能夠來看閉包了:學習
前面說過,函數能夠訪問函數做用域鏈中的變量,但若是咱們想在函數外訪問函數內卻不行了。好比這個例子:this
function myfunction(){ var num=21; } alert(num); // error
眼前就有一個變量,尷尬的是咱們調用不了。
想一想辦法:根據函數能夠訪問函數做用域鏈中的變量這句話,若是咱們在函數內再定義一個函數,讓這個新函數訪問舊函數裏的變量,而後返回這個函數,而後直接運行那個舊函數不就能夠了嗎!設計
function myfunction(){ var num=21; function newfunction(){ alert(num); } return newfunction; } var result=myfunction(); result(); // 21
沒有任何問題,在函數外面成功訪問到了num變量。
恭喜你,你剛剛建立了一個閉包。。。是的,這個就是閉包。閉包就是指有權訪問另外一個函數做用域中的變量的函數。建立閉包的常見方式,就是在一個函數內部建立另外一個函數。code
明白了閉包,再來看爲何能夠把閉包和this放一塊兒理解:對象
首先你須要記住的是:this的對象是運行時基於函數的執行環境綁定的,它的指向徹底取決於函數的調用方式ip
很少說來看兩個經典例子:
第1個例子
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()()); //"The Window"(在非嚴格模式下)
第2個例子
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()()); //"My Object"
關於這兩個例子,我我的感受《Javascript高級程序設計》這本書裏講得不夠明確。個人理解是第1個例子裏是在全局環境中調用了這個函數,因此this關鍵字最終指向了全局對象The Window,從而利用閉包在全局環境中調用了The Window;第2個例子不一樣,它返回的是that的name,而this對象被賦值給了that變量,就是說this對象和that捆綁在了一塊兒,那麼在調用這個方法時至關於在object裏利用閉包去尋找最終變量(that是引用着object的),因此只能找到My Object變量。
這兩個例子很是好,怎麼個好法呢。它們完整解釋(展示)了閉包的做用機理或者說過程,同時又證實了this關鍵字在函數被不一樣的環境調用時的指向是不同的。
怎麼樣,看到這裏是否是完全明白了閉包和this關鍵字呢。