第一章 載入與執行指令碼
這一章主要提供了幾個提高指令碼載入速度技巧:
1、由於script標籤會阻塞html頁面的載入,瀏覽器會等到載入完script後才渲染頁面,以防止script
會對頁面DOM元素進行操作,因此建議將script標籤放在底部</body>前面,同事使用defer屬性(支援ie)
2、將多個指令碼合并成為一個,減少http請求
3、動態載入指令碼,通過ajax或者動態建立script標籤
第二章 資料訪問
這一章主要講解如果提高訪問資料的速度,文章對比了中繼資料類型,局部變數,數組,對象四種儲存資料
方式的效能,其中中繼資料類型是最高,其次是局部變數,接著就是數組和對象。這裡我們可以理解為什麼jquery要把window對象作為
參數傳進去,目的就是為了提高效能。
js範圍:(scope)
Each time a variable is encountered during the function’s execution, the process of
identifier resolution takes place to determine where to retrieve or store the data. During
this process, the execution context’s scope chain is searched for an identifier with the
same name. The search begins at the front of the scope chain, in the execution function’s
activation object. If found, the variable with the specified identifier is used; if not, the
search continues on to the next object in the scope chain. This process continues until
either the identifier is found or there are no more variable objects to search, in which
case the identifier is deemed to be undefined. The same approach is taken for each
dentifier found during the function execution
每執行一個函數js會建立一個“執行環境”(execution context),每個執行環境都有一個範圍鏈(scope chain)
當執行完畢後,執行環境也同時被銷毀。當建立完“執行環境”後,所有函數變數會被複製到“執行環境”中,之後會建立一個
activation object(使用中的物件),這個對象包含了函數的所有局部變數,參數命名,參數集合和this。然後這個對象會被壓到
scope chain的頂端。
再引用文章的一段話:
The deeper into the execution context’s scope chain an
identifier exists, the slower it is to access for both reads and writes. Consequently, local
variables are always the fastest to access inside of a function, whereas global variables
will generally be the slowest (optimizing JavaScript engines are capable of tuning this
in certain situations). Keep in mind that global variables always exist in the last variable
object of the execution context’s scope chain, so they are always the furthest away to
resolve.
執行一個函數會從當前執行環境開始位置搜尋變數,變數處於執行環境範圍鏈的位置越深,讀寫變數的速度就越慢。
通常情況下,函數中的局部變數訪問速度是最快的,而相反全域變數是最慢的。因此我們應該盡量將全域變數私人化,降低搜尋
變數的時間。
不過文章也提到隨著瀏覽器的發展,瀏覽器本身對js進行最佳化,到了chome,Safari 4,IE8影響就不怎麼明顯了
這裡引用http://hi.baidu.com/meteoric_cry/blog/item/7df9af2b92caa2f0e7cd40dd.html一段話對範圍的描述:
a、javascript的範圍機制
通過編譯,javascript代碼已經翻譯成了文法樹,然後會立刻按照文法樹執行。
進一步的執行過程,需要理解javascript的範圍機制:詞法範圍(lexcical scope)。
通俗地講,就是javascript變數的範圍是在定義時決定而不是執行時決定,也就是說詞法範圍取決於源碼,
編譯器通過靜態分析就能確定,因此詞法範圍也叫做靜態範圍(static scope)。
但需要注意,with和eval的語義無法僅通過靜態技術實現,所以只能說javascript的範圍機制非常接近詞法範圍(lexical scope).
javascript引擎在執行每個函數執行個體時,都會建立一個執行環境(execution context)。
執行環境中包含一個調用對象(call object), 調用對象是一個scriptObject結構(scriptObject是與函數相關的一套靜態系統,
與函數執行個體的生命週期保持一致),用來儲存內部變數表varDecls、內嵌函數表funDecls、父級引用列表upvalue等文法分析結構
(注意varDecls和funDecls等資訊是在文法分析階段就已經得到,並儲存在文法樹中。函數執行個體執行時,會將這些資訊從文法樹複製到scriptObject上)。
b、javascript範圍機制的實現方法
詞法範圍(lexical scope)是javascript的範圍機制,還需要理解它的實現方法,就是範圍鏈(scope chain)。
範圍鏈是一個name lookup機制,首先在當前執行環境的scriptObject中尋找,沒找到,則順著upvalue到父scriptObject中尋找,
一直lookup到全域調用對象(global object)。
通過上面亮點,我們可以看出,js執行函數時候,搜尋變數會在當前執行環境的scope chain中尋找,如果找不到,就需要繼續往上找
那麼這種搜尋必定會帶來效能的損耗,因此文章建議使用私人變數,盡量減少變數的搜尋。
第三章 js操作DOM
這一章講到js操作DOM時,對效能的影響很大,因此我們應該盡量減少對DOM的操作,盡量減少頁面的重繪和迴流。
其中提到了一些技巧:
1、盡量減少對DOM的讀取次數,對於迴圈體,我們可以先將元素賦值給局部變數,然後再在迴圈體中使用
2、使用innerHTML進行批量修改
3、緩衝HTML Collections 的長度
4、避免重繪和迴流,批量修改樣式,使用cssText或者class名修改樣式,批量修改dom元素
5、將dom元素display置為none後進行操作,然後再顯示
6、使用document.createDocumentFragment();複製一份需要更新的節點,然後修改後在更新原來的節點