優化JavaScript總結分享(上)

原本想整理一篇完整的JavaScript優化知識點出來跟你們討論分享一下的,可是因爲最近我的的時間比較少,因此先整理了兩個知識點,以後有時間了再繼續整理後面的。不喜歡勿噴,有錯誤的歡迎大佬指點。

1.引用 script標籤的優化

2019/05/14/01:30javascript

  • 多數瀏覽器都是使用單一的進程來處理用戶界面(UI)和JavaScript腳本執行,因此同一時刻只能作一件事,所以就會形成瀏覽器的堵塞狀態,JavaScript腳本執行過程耗時越久,瀏覽器等待響應的時間就越長。(也就是說當頁面加載的時候,遇到script標籤的時候,頁面加載就會被終止,等到JavaScript腳本執行完畢後,再繼續加載頁面,這樣給用戶的體驗特別不會,很容易首次加載頁面的時候出現白屏狀態。)

優化方式

傳統的方式java

傳統的方式就是,把JavaScript的腳本放到head標籤以後</body>以前,也就把script標籤放到最尾處,來確保頁面加載完以後才執行JavaScript腳本,從而達到一些沒必要要的阻塞。(可能這也是咱們平時用得比較多的方式)es6

延遲JavaScript腳本執行面試

1.HTML4爲script標籤擴展了一個Defer屬性,指定這個屬性的script標籤的腳本不會修改DOM,所以代碼能安全的延遲執行。加上這個屬性的script標籤的腳本能夠放在DOM的任意位置,當瀏覽器加載到它是,它會被下載,但不會被執行,因此不能阻塞頁面的方面,它會等到頁面加載完成後,在windown的load()函數以後執行。
<script type="text/javascript" src="./a.js" defer="defer"></script>

<script type="text/javascript">
    console.log("b")
</script>


<script type="text/javascript">
    window.onload = function () {
        console.log("c")
    }
//這個例子,最終輸出的順序是b,a,c
</script>

clipboard.png

2.在H5的時候,script又擴展了一個async屬性,它與defer相同點就是都是採用並行下載,不會在下載的過程形成頁面的阻塞狀況;不一樣點就是,它們的執行時機:async加載完以後,自動執行(也就是說,當加載到它的時候,瀏覽器能夠繼續往下加載頁面,當它加載完以後,它就會自動執行,而不須要等到頁面加載完以後再執行,也不用頁面加載等它執行完再日後執行);而dafer要等頁面加載完成後纔會執行。

合拼JavaSript腳本瀏覽器

由於每一個script標籤初始下載是=時都會阻塞頁面渲染,因此減小頁面包含的script標籤數量也有助於頁面加載性能的優化。(若是頁面有不少的script標籤,沒個script標籤都會發送一次http請求( http://tool.oschina.net/jscom...),從而浪費了不少不必的時間,咱們能夠經過某些在線工具將多個script標籤合拼成一個script標籤,最終頁面只引用了一個script,也就是隻發送了一次http請求,這樣加載性能會比以前加載多個script標籤快)

2.做用域/鏈的優化

2019/05/15/02:05緩存

  • JavaScript的做用域一樣關係到性能的問題安全

    • 在es6以前JavaScript沒有什麼塊級做用域所說,只有全局做用域和函數做用域。(沒什麼塊級做用域有時會給咱們帶不少莫民奇妙的東西),例如:一個經典的面試題:
//結果輸出什麼?
    for(var i = 0; i<10;i++){
            setTimeout(function () {
                console.log(i)
            },1000)
        }

咱們指望的結果是輸出0-9。可是結果拼不是咱們想這樣,這玩(diao)意(mao)既然輸出十次10.爲何會這樣?由於當setTimeout執行的時候,for循環已經完成,已經變成了10。閉包

怎樣解決?(在es6沒有到來以前,通常都是同閉包的方法把做用域緩存起來)async

for(var i = 0; i<10;i++){
        (function(i){
            setTimeout(function () {
                console.log(i)
            },1000)
        })(i)
    }
//結果輸出爲0-9

最後輸出的結果就跟咱們期待的同樣了,可是上面使用了閉包,閉包也涉及到做用域鏈的性能問題;由於閉包的屬性包含了與執行環境做用域相同的對象的引用,所以致使閉包裏面的變量沒辦法被銷燬,從而佔用了更多的內存空間,也有可能致使內存泄漏問題,因此使用閉包時仍是要謹慎,它關係到內存以及執行速度。函數

//上面代碼優化後
for(let i = 0; i<10;i++){
            setTimeout(function () {
                console.log(i)
            },1000)
        }

2.儘可能使用局部變量緩存全局變量

  • 在實際開發中儘可能使用局部變量緩存全局變量,由於,到一個函數屢次訪問全局變量的時候,會出現一個做用域練查找的過程,全局做用域位置越深找到的時間就越久,所以這也會涉及到性能的執行速度問題。例如:下面這段簡單的代碼,在瀏覽器打開執行看到仍是挺快的,沒什麼問題;可是,它三次引用了obj.name這個全局變量,在這個查找的過程當中必須遍歷整個做用域鏈,直到找到爲止(幸好這個全局變量比較淺,幸好,這段代碼只引用了三次;要這個全局變量在window對象上面呢,要是這個全局變量會被引用幾千萬次呢),而後咱們能夠將這個屢次被引用的全局變量,用局部變量存起來,這樣不管這個全局變量被引用屢次,它都只會查找一次。
let obj = {
        name:"July"
}

function Person() {
    console.log(obj.name +"去吃飯",obj.name +"去睡覺",obj.name +"去打籃球")
}

Person()

//改

let obj = {
        name:"July"
}

function Person() {
    let name = obj.name
    console.log(name +"去吃飯",name +"去睡覺",name +"去打籃球")
}

Person()

3.儘可能不要使用動態做用域,由於他們會改變執行環境的做用域鏈。好比with()語句和try{}catch(){}的catch(){}字句...,它們都會改變執行環境的做用域鏈。好比下面這段代碼:with會把一個包含了obj所有屬性的新的可變變量置於做用域鏈的頭部,使得訪問obj對象屬性速度很是快,可是訪問局部變量則變慢了,所以仍是儘可能避免使用。

let obj = {
    name:"July"
}

function Person() {
    with(obj){
        console.log(name +"去吃飯",name +"去睡覺",name +"去打籃球")
    }
}
Person()
相關文章
相關標籤/搜索