深刻理解javascript原型和閉包(14)——從【自由變量】到【做用域鏈】

先解釋一下什麼是「自由變量」。javascript

在A做用域中使用的變量x,卻沒有在A做用域中聲明(即在其餘做用域中聲明的),對於A做用域來講,x就是一個自由變量。以下圖html

如上程序中,在調用fn()函數時,函數體中第6行。取b的值就直接能夠在fn做用域中取,由於b就是在這裏定義的。而取x的值時,就須要到另外一個做用域中取。到哪一個做用域中取呢?前端

有人說過要到父做用域中取,其實有時候這種解釋會產生歧義。例如:java

 

因此,不要在用以上說法了。相比而言,用這句話描述會更加貼切——要到建立這個函數的那個做用域中取值——是「建立」,而不是「調用」,切記切記——其實這就是所謂的「靜態做用域」。web

對於本文第一段代碼,在fn函數中,取自由變量x的值時,要到哪一個做用域中取?——要到建立fn函數的那個做用域中取——不管fn函數將在哪裏調用。面試

 

上面描述的只是跨一步做用域去尋找。json

若是跨了一步,還沒找到呢?——接着跨!——一直跨到全局做用域爲止。要是在全局做用域中都沒有找到,那就是真的沒有了。閉包

這個一步一步「跨」的路線,咱們稱之爲——做用域鏈app

咱們拿文字總結一下取自由變量時的這個「做用域鏈」過程:(假設a是自由量)webapp

第一步,如今當前做用域查找a,若是有則獲取並結束。若是沒有則繼續;

第二步,若是當前做用域是全局做用域,則證實a未定義,結束;不然繼續;

第三步,(不是全局做用域,那就是函數做用域)將建立該函數的做用域做爲當前做用域;

第四步,跳轉到第一步。

 

以上代碼中:第13行,fn()返回的是bar函數,賦值給x。執行x(),即執行bar函數代碼。取b的值時,直接在fn做用域取出。取a的值時,試圖在fn做用域取,可是取不到,只能轉向建立fn的那個做用域中去查找,結果找到了。

 

這一節看似很輕鬆的把做用域鏈引出來,並講完了。之全部輕鬆是有前幾節的基礎,不然將很難解釋。

接下來我們開始正式說說一直期待依舊的朋友——閉包。敬請期待下一節。

---------------------------------------------------------------------------

本文已更新到《深刻理解javascript原型和閉包系列》的目錄,更多內容可參見《深刻理解javascript原型和閉包系列》。

另外,歡迎關注個人微博

學習做者教程:《前端JS高級面試》《前端JS基礎面試題》《React.js模擬大衆點評webapp》《zepto設計與源碼分析》《json2.js源碼解讀

相關文章
相關標籤/搜索