提到作用域,有一句話大家(有js開發經驗者)可能比較熟悉:“javascript沒有塊級作用域”。所謂“塊”,就是大括號“{}”中間的語句。例如if語句:
再比如for語句:
所以,我們在編寫程式碼的時候,不要在“塊”裡面宣告變數,要在程式碼的一開始就宣告好了。以避免發生歧義。如:
其實,你光知道“javascript沒有塊級作用域”是完全不夠的,你需要知道的是——javascript除了全域性作用域之外,只有函式可以建立的作用域。
所以,我們在宣告變數時,全域性程式碼要在程式碼前端宣告,函式中要在函式體一開始就宣告好。除了這兩個地方,其他地方都不要出現變數宣告。而且建議用“單var”形式。
jQuery就是一個很好的示例:
下面繼續說作用域。作用域是一個很抽象的概念,類似於一個“地盤”
如上圖,全域性程式碼和fn、bar兩個函式都會形成一個作用域。而且,作用域有上下級的關係,上下級關係的確定就看函式是在哪個作用域下建立的。例如,fn作用域下建立了bar函式,那麼“fn作用域”就是“bar作用域”的上級。
作用域最大的用處就是隔離變數,不同作用域下同名變數不會有衝突。例如以上程式碼中,三個作用域下都宣告瞭“a”這個變數,但是他們不會有衝突。各自的作用域下,用各自的“a”。
說到這裡,我們們又可以拿出jquery原始碼來講講了。
jQuery原始碼的最外層是一個自動執行的匿名函式:
為什麼要這樣做呢?
原因就是在jQuery原始碼中,宣告瞭大量的變數,這些變數將通過一個函式被限制在一個獨立的作用域中,而不會與全域性作用域或者其他函式作用域的同名變數產生衝突。
全世界的開發者都在用jQuery,如果不這樣做,很可能導致jQuery原始碼中的變數與外部javascript程式碼中的變數重名,從而產生衝突。
作用域這塊只是很不好解釋,我們們就小步快跑,一步一步慢慢展示給大家。
下一節將把作用域和執行上下文環境結合起來說一說。
可見,要理解閉包,不是一兩句話能說清楚的。。。
---------------------------------------------------------------------------
本文已更新到《深入理解javascript原型和閉包系列》的目錄,更多內容可參見《深入理解javascript原型和閉包系列》。
另外,歡迎關注我的微博。
學習作者教程:《前端JS高階面試》《前端JS基礎面試題》《React.js模擬大眾點評webapp》《zepto設計與原始碼分析》《json2.js原始碼解讀》