寫在前面
聽聞大佬們在寫一些框架或者庫的時候,到處都隱藏了一些細節,所以閱讀他們的源代碼,無論從性能優化、還是JS API的學習、亦或是代碼風格等方面給到我們很多啟發。這兩天我翻看了一下jQuery1.x的源代碼,看到了這麼一段,著實讓我覺得很細節,在這兒和大家分享一下。
不再廢話,看代碼
看上圖,整個jquery的初始化做成被包裹在了一個自執行函數中,這很容易理解,因為自執行函數在執行時創建了自己的作用域,在jquery中聲明的變量不小心汙染全局空間的可能。
但令人疑惑的是,為什麼這個自執行函數還會把window回想作為一個函數參數傳進來呢?在自執行函數內部就能訪問了window呀 ?
從作用域鏈談起
解答上面的問題,其實也不難,這就要提到一個概念: “作用域鏈”。
JS中函數也是一個對象,函數擁有可以通過代碼訪問的屬性和一系列僅供js引擎訪問的內部屬性。
其中一個內部屬性是[[scope]]。該內部屬性包含了函數被創建的作用域中對象的集合,這個集合被稱為函數的作用域鏈,它決定了哪些數據能被函數訪問 函數被創建時,它的作用域鏈中會填入一個全局對象,該全局對象包含了所有全局變量。
執行函數時,會創建一個稱為‘運行期上下文’的內部對象,運行期上下文定義了函數執行的環境。每個運行期上下文都有自己的作用域鏈,用於標識符解析。在解析這些標識符時,JS引擎會沿著自己的作用域鏈,逐步地往上查找,找到標識符,則停止。
知道了作用域鏈的查找原理,那麼上面的問題也就好回答了:
之所以要把window對象傳入自執行函數,是因為jquery源碼中,應該存在較多的對window對象的引用,此時就應當把window對象置於作用域鏈的頭部,這樣就避免了需要window對象時,需要跳過頭部的作用域向上查找,這樣有助於提升性能。
再說說 “with”
相信很多人在面試時都會被問到 “為什麼不建議使用 with ?”
在這主要由兩個原因:
- with 在嚴格模式下不能使用
- 第二點也就是跟我們上面提到的作用域鏈有關了。 with 會創建自己的所用域,使得作用域鏈增長,此時在 with 代碼塊內部訪問外部的變量時,會造成一定的性能損失。
OK,上面就是我想給大家分享的內容。
過年啦!最後祝各位看到文章的朋友們漲薪漲不停!!!
閱讀更多 盆盆兒WEB前端 的文章