JavaScript之閉包(closure)

「JavaScript中的函數運行在它們被定義的做用域裏,而不是它們被執行的做用域裏。」

一些關於閉包的定義:javascript

  1. 閉包是指有權訪問另外一個函數做用域中變量的函數 --《JS高級程序設計第三版》 p178
  2. 函數對象能夠經過做用域鏈相關聯起來,函數體內部的變量均可以保存在函數做用域內,這種特性稱爲 ‘閉包’ 。 --《JS權威指南》 p183
  3. 內部函數能夠訪問定義它們的外部函數的參數和變量(除了thisarguments)。 --《JS語言精粹》 p36

要理解js中的閉包必須清楚另外一個概念scope。JS中採用」鏈式做用域」結構(chain scope),子對象能夠一級一級地向上尋找全部父對象的變量。html

JS的scope基於function,而function是能夠做爲普通對象處處傳遞的,常常會有一個function內部定義的函數放到其餘地方使用的狀況。所謂的閉包就是當函數在其餘地方使用的時候能保存下函數所須要的運行環境,也便是函數能保存下函數誕生時的環境。java

var a=1

var b=function(){
    return a+1 
}

b() // => 2

這個案例中,變量a是一個依賴閉包機制所捕獲的自由變量,也所以函數b能夠被正常執行。(做者:項昊凡 連接:https://www.zhihu.com/question/34547104/answer/59560912)閉包

另外一種說法:函數

代碼指令執行時候,會處於必定的環境,單純將代碼保存下來,仍是不夠的,須要將代碼所處的環境也保存下來。閉包實際上是,將代碼跟代碼所處於的環境作爲一個總體來看待。周圍的環境,表現爲代碼所使用的數據。在有些語言中,這個概念叫代碼塊(block),匿名函數(lambda)等等。this

數據跟代碼再也不人爲割裂開來,統一塊兒來看待。閉包就會是很天然的概念。數據能夠傳遞,從一個地方傳遞到另外一個地方,而且之後再使用。閉包從某個角度來講,也是數據,固然也能夠傳遞,從一個函數傳遞到另外一個函數,也能夠保持下來,之後再調用。由於將環境也保持下來了,之後調用的時候,就還原當時的狀況,延遲執行,就很容易,很天然地實現了。而延遲執行有什麼做用?就是另外一個話題了。(做者:黃兢成 連接:https://www.zhihu.com/question/24084277/answer/28476841)spa

再一個Javascript閉包的例子:.net

function A(x){
    return function B(y) {
         return x*y
    }
}

首先,變量x對於B(y)來講是一個外部自由變量,B()調用時須要x;其次,B的外部環境A包含x;再次,JS容許B訪問A的變量。設計

轉一道有意思的題目:code

function fun(n,o) {
 console.log(o)
 return {
  fun:function(m){
   return fun(m,n);
  }
 };
}
var a = fun(0); a.fun(1); a.fun(2); a.fun(3);//undefined,?,?,?
var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?
var c = fun(0).fun(1); c.fun(2); c.fun(3);//undefined,?,?,?
//問:三行a,b,c的輸出分別是什麼?

答案請查閱原文:http://www.jb51.net/article/75450.htm

最後貼上阮一峯老師關於閉包的介紹http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
相關文章
相關標籤/搜索