01.20 jQuery源碼一個小細節,卻很好地體現了性能優化的思想,很優秀

寫在前面

聽聞大佬們在寫一些框架或者庫的時候,到處都隱藏了一些細節,所以閱讀他們的源代碼,無論從性能優化、還是JS API的學習、亦或是代碼風格等方面給到我們很多啟發。這兩天我翻看了一下jQuery1.x的源代碼,看到了這麼一段,著實讓我覺得很細節,在這兒和大家分享一下。

不再廢話,看代碼


jQuery源碼一個小細節,卻很好地體現了性能優化的思想,很優秀

看上圖,整個jquery的初始化做成被包裹在了一個自執行函數中,這很容易理解,因為自執行函數在執行時創建了自己的作用域,在jquery中聲明的變量不小心汙染全局空間的可能。

但令人疑惑的是,為什麼這個自執行函數還會把window回想作為一個函數參數傳進來呢?在自執行函數內部就能訪問了window呀 ?

從作用域鏈談起

解答上面的問題,其實也不難,這就要提到一個概念: “作用域鏈”。

JS中函數也是一個對象,函數擁有可以通過代碼訪問的屬性和一系列僅供js引擎訪問的內部屬性。

其中一個內部屬性是[[scope]]。該內部屬性包含了函數被創建的作用域中對象的集合,這個集合被稱為函數的作用域鏈,它決定了哪些數據能被函數訪問 函數被創建時,它的作用域鏈中會填入一個全局對象,該全局對象包含了所有全局變量。

執行函數時,會創建一個稱為‘運行期上下文’的內部對象,運行期上下文定義了函數執行的環境。每個運行期上下文都有自己的作用域鏈,用於標識符解析。在解析這些標識符時,JS引擎會沿著自己的作用域鏈,逐步地往上查找,找到標識符,則停止。

知道了作用域鏈的查找原理,那麼上面的問題也就好回答了:

之所以要把window對象傳入自執行函數,是因為jquery源碼中,應該存在較多的對window對象的引用,此時就應當把window對象置於作用域鏈的頭部,這樣就避免了需要window對象時,需要跳過頭部的作用域向上查找,這樣有助於提升性能。

再說說 “with”

相信很多人在面試時都會被問到 “為什麼不建議使用 with ?”

在這主要由兩個原因:

  1. with 在嚴格模式下不能使用
  2. 第二點也就是跟我們上面提到的作用域鏈有關了。 with 會創建自己的所用域,使得作用域鏈增長,此時在 with 代碼塊內部訪問外部的變量時,會造成一定的性能損失。

OK,上面就是我想給大家分享的內容。

過年啦!最後祝各位看到文章的朋友們漲薪漲不停!!!


分享到:


相關文章: