【前端性能優(yōu)化】高性能JavaScript讀書筆記

封面一隅 & 搶鏡的比翼鳥書簽

曾經(jīng)看過一篇文章,有一句話這樣說:

只有在大學(xué)的圖書館里傲茄,你才能真正賺回你交的學(xué)費结啼。

臨近畢業(yè)伴网,還想再去圖書館多轉(zhuǎn)轉(zhuǎn)。偶然在架子上發(fā)現(xiàn)了這本書妆棒,一看作者是寫大名鼎鼎的紅寶書的人澡腾,就很感興趣。再者糕珊,最近用 JavaScript 刷 LeetCode 發(fā)現(xiàn)动分,提交顯示 JavaScript 要比 Go 語言或 Python 有更大的時間和內(nèi)存消耗,也使我把了解 JavaScript 內(nèi)存機制和性能優(yōu)化提上了日程红选。

本書雖然有部分章節(jié)涉及到的問題有一定年代感澜公,比如最后一章[工具],由于前端技術(shù)的快速迭代和瀏覽器的不斷支持下喇肋,已經(jīng)不適用了坟乾。但是這本書的前面章節(jié)詳細地從js運行、訪問蝶防、代碼結(jié)構(gòu)優(yōu)化甚侣、異步編程等多方面講解了 JavaScript 優(yōu)化的策略,解答了我刷題時的疑惑间学,也讓我認識到之前秋招面試的時候遇到的一些坑殷费,還是有許多需要引起重視的知識體系需要不斷擴容。

總之低葫,這本書不僅是對前端性能優(yōu)化基礎(chǔ)知識的一種補充掌握详羡,還有很多底層原理的實現(xiàn)值得學(xué)習(xí),推薦有項目經(jīng)驗并希望提升Web應(yīng)用性能的前端開發(fā)人員閱讀嘿悬。

前端性能優(yōu)化

下面是我認知的前端性能優(yōu)化的策略实柠,本書主要著手 JavaScript 優(yōu)化展開闡述。

  • JavaScript優(yōu)化
  • 非核心代碼異步加載
  • 瀏覽器緩存
  • 使用CDN
  • DNS預(yù)解析
  • 優(yōu)化資源
  • 清理不必要的依賴

本文目錄


高性能JavaScript

早期善涨,IE瀏覽器的JS引擎基于“靜態(tài)垃圾回收機制(Static Garbage Collection)”窒盐,該引擎監(jiān)視內(nèi)存中固定數(shù)量的對象來確定何時進行垃圾回收茶行。隨著Web應(yīng)用的日益發(fā)展,JS引擎吃不消了登钥。

雖然其他瀏覽器有著更加完善的GC和更好的性能,但大多數(shù)都是使用JS解釋器來執(zhí)行娶靡。

這也正解釋了開篇刷 LeetCode 題時的困惑牧牢,解釋型代碼為什么沒有編譯型代碼快?

因為姿锭,解釋型代碼必須經(jīng)歷把代碼轉(zhuǎn)換成計算機指令的過程塔鳍。無論解釋器多么智能,都會帶來一些性能的消耗呻此。

解釋型代碼轉(zhuǎn)換

而編譯器已經(jīng)有了各種各樣的優(yōu)化轮纫,可以基于詞法分析去判斷代碼想實現(xiàn)什么,產(chǎn)生完成任務(wù)的運行最快的機器碼焚鲜。解釋器很少有這樣的優(yōu)化掌唾,往往代碼怎么寫就怎么被執(zhí)行。

2008年忿磅,JS引擎收獲最大的一次性能升級糯彬,該引擎的研發(fā)代號為V8。V8是一款為 JavaScript 打造的實時(JIT)編譯引擎葱她,它把 JavaScript 代碼轉(zhuǎn)化為機器碼來執(zhí)行撩扒。緊接著其他瀏覽器也優(yōu)化了JS引擎,這些只是編譯器層面的優(yōu)化吨些,代碼的性能依然需要開發(fā)人員關(guān)注搓谆。

編譯器層面的優(yōu)化

一、瀏覽器中的 JavaScript

瀏覽器中js代碼的執(zhí)行可能會阻塞瀏覽器的其他進程豪墅,下邊列出了幾點棘手的問題以及優(yōu)化方式泉手。

  1. 腳本阻塞:將<script>標(biāo)簽放在頁面底部,</body>閉合標(biāo)簽之前偶器。

  2. 延遲時間:

    1. 內(nèi)嵌<script>不緊跟<link>標(biāo)簽
    2. 運用打包工具螃诅,合并js文件
  3. 無阻塞加載js:關(guān)鍵是在window對象的load事件觸發(fā)后再下載腳本

    1. 使用<script>標(biāo)簽的defer屬性
      注意:defer屬性僅當(dāng)src屬性聲明時才生效

    2. 動態(tài)腳本加載:使用動態(tài)創(chuàng)建的<script>元素來下載并執(zhí)行代碼
      注意:需要通過偵聽事件,跟蹤并確保腳本下載完成并準(zhǔn)備就緒
      優(yōu)勢是跨瀏覽器兼容性和易用状囱,也是最通用的無阻塞加載的策略术裸。

    3. 使用 XHR 對象下載 JavaScript 代碼并注入頁面中

      局限性:JavaScript 文件必須和所請求的頁面同域,不適用大型Web項目亭枷。

無阻礙腳本加載工具:YUI3袭艺、LazyLoad、LABjs

通過以上策略叨粘,可以極大地提高JavaScript的Web應(yīng)用的性能猾编。
此外瘤睹,還有一些策略例如:減少js文件的大小、限制HTTP請求數(shù)答倡。這兩點策略轰传,隨著Web應(yīng)用的日益復(fù)雜,可行性也隨之降低瘪撇,也不是做的越極致效果越好获茬,需要實際情況具體分析。

二倔既、數(shù)據(jù)存儲的位置

數(shù)據(jù)存儲的位置關(guān)系到數(shù)據(jù)的檢索速度恕曲,直接影響代碼執(zhí)行的效率。JavaScript 有以下四種基本的數(shù)據(jù)存儲位置:

  1. 字面量:值的記法渤涌,包括:字符串佩谣、數(shù)字、布爾值实蓬、對象茸俭、數(shù)組、函數(shù)安皱、正則表達式瓣履,還有特殊的 null 和 undefined 值
  2. 本地變量:使用 var/let/const 關(guān)鍵字定義的數(shù)據(jù)存儲單元
  3. 數(shù)組元素:以數(shù)字為索引,存儲在 JavaScript 數(shù)組對象內(nèi)部
  4. 對象成員:以字符串作為索引练俐,存儲在 JavaScript 對象內(nèi)部

標(biāo)識符解析的性能

在函數(shù)的執(zhí)行過程中袖迎,每遇到一個變量,都會經(jīng)歷一次標(biāo)識符解析過程以決定從哪里獲取或存儲數(shù)據(jù)腺晾。該過程的搜索執(zhí)行環(huán)境是作用域鏈燕锥,這個搜索過程會影響性能。

注意:總的趨勢是悯蝉,標(biāo)識符所在位置越深归形,它的讀寫速度越慢。若采用優(yōu)化過的 JavaScript 引擎的瀏覽器性能損失會大大減少鼻由。

原型鏈和嵌套成員也遵從此關(guān)系暇榴。

注意作用域鏈的改變

可以在執(zhí)行時改變作用域鏈,影響性能的語句:

  1. with 語句:會導(dǎo)致一個新的變量對象被置于作用域鏈的首位蕉世,造成訪問特定對象的屬性非嘲簦快,而訪問局部變量則變慢狠轻。
    建議:棄用

  2. try-catch語句中的 catch 子句:會把異常對象推入一個變量對象并置于作用域的首位奸例。
    建議:將錯誤委托給一個函數(shù)處理

閉包

閉包的[[scope]]屬性包含了與執(zhí)行環(huán)境作用域鏈相同的對象的引用,同時會影響內(nèi)存開銷和執(zhí)行速度向楼,應(yīng)小心使用閉包查吊。

策略

可以通過把常用的數(shù)組元素谐区、跨域變量保存在局部變量中來改善性能。

這種策略不推薦用于對象的成員方法逻卖,會改變this的值宋列。

三、DOM 編程

瀏覽器中通常會把 DOM 和 JavaScript 獨立實現(xiàn)评也,所以訪問DOM元素消耗很大炼杖。

策略:減少訪問DOM的次數(shù),把運算留給ECMAScript一端仇参。

innerHTML 對比 DOM 方法

舊版瀏覽器中,使用innerHTML會更快一些婆殿。在基于 WebKit 內(nèi)核的新版瀏覽器中诈乒,用DOM略勝一籌。

策略:根據(jù)可讀性婆芦、穩(wěn)定性怕磨、團隊習(xí)慣、代碼風(fēng)格來綜合決定消约。

節(jié)點克隆

節(jié)點克隆element.cloneNode()比創(chuàng)建新元素document.createElement更有效率肠鲫,但不明顯。

HTML集合

返回值是集合的方法:

  • document.getElementByName()
  • document.getElementByClassName()
  • Document.getElementByTagName()

返回值是集合的屬性:

  • document.images
  • document.links
  • document.forms
  • document.forms[0].elements

HTML集合是包含DOM節(jié)點引用的類數(shù)組對象或粮。和數(shù)組的區(qū)別是沒有push和slice方法导饲,有l(wèi)ength屬性和數(shù)字索引的方式訪問元素。

HTML集合低效之源:假定實時態(tài) assumed to be live

策略:

  1. 把集合的長度緩存到一個局部變量中氯材,在循環(huán)條件的退出語句中使用該變量渣锦。

  2. 使用數(shù)組拷貝。

    function toArr() {
        for (var i = 0, arr = [], len = coll.length; i < len; i++) {
            arr[i] = coll[i];
        }
        return arr;
    }
    

遍歷DOM

屬性名 被替代的屬性
children childNodes
childElementCount childNodes.length
firstElementChild firstChild
lastElementChild lastChild
nextElementSibling nextSibling
previousElementSibling previousSibling

選擇器API

queryAelectorAll()firstElementChild()方法使用CSS選擇器作為參數(shù)并返回一個NodeList氢哮,不會返回HTML集合袋毙。適合處理大量組合查詢。

重排和重繪

在瀏覽器的渲染過程中冗尤,瀏覽器會在下載完頁面所有組件之后听盖,解析并生成兩個數(shù)據(jù)結(jié)構(gòu):

  • DOM Tree(DOM樹)
  • Render Tree(渲染樹)

一旦上述兩種結(jié)構(gòu)構(gòu)建完成,瀏覽器就開始繪制(paint)頁面元素裂七。

注:對重排和重繪的理解是非常必要的

重排 Reflow

定義:當(dāng)DOM結(jié)構(gòu)的變化影響了元素的幾何屬性皆看,瀏覽器需要根據(jù)樣式來重新計算元素出現(xiàn)的位置。瀏覽器會使渲染樹中受到影響的部分失效背零,并重新構(gòu)造渲染樹悬蔽。

觸發(fā)Reflow的條件:

  • 添加或刪除可見的DOM元素
  • 元素位置改變:如,添加動畫效果
  • 元素尺寸改變:如捉兴,改變邊框?qū)捀咝А?nèi)外邊距等
  • 內(nèi)容改變:如录语,改變段落文字行數(shù)、圖片替換等
  • 瀏覽器Resize窗口(移動端不會出現(xiàn))
  • 修改默認字體
  • 頁面渲染器初始化

特別的:當(dāng)滾動條出現(xiàn)時禾乘,會觸發(fā)整個頁面的重排

重繪 Repaint

定義:完成重排后澎埠,瀏覽器會根據(jù)渲染樹重新繪制受影響的部分到屏幕中。

不是所有的DOM變化都會影響幾何屬性始藕,例如改變一個元素的背景色只會發(fā)生一次重繪蒲稳。

特別的,要注意分析改變所影響的階段是重排還是重繪伍派。

綜上江耀,重排和重繪都是昂貴的操作,會導(dǎo)致Web應(yīng)用反應(yīng)遲鈍诉植。所以祥国,應(yīng)該盡可能減少這類過程的發(fā)生。

渲染樹的變化的排隊和刷新

瀏覽器會通過隊列化批量執(zhí)行來優(yōu)化重排過程晾腔。

以下獲取布局的操作會導(dǎo)致隊列刷新:

  • offsetTop舌稀、offsetLeft、offsetWidth灼擂、offsetHeight
  • scrollTop壁查、scrollLeft、scrollWidth剔应、scrollHeight
  • clientTop睡腿、clientLeft、clientWidth峻贮、clientHeight
  • getComputedStyle()

修改樣式時嫉到,應(yīng)避免以上屬性。

策略:不要在布局信息改變時操作它月洛。

最小化重排和重繪

策略:

  1. 合并多次對DOM和樣式的修改何恶,然后一次處理掉。(n -> 1)

    如:cssText屬性嚼黔,className屬性等细层。

  2. 盡量減少offsets等布局信息的獲取次數(shù),方法是獲取一次起始位置的值唬涧,在動畫循環(huán)中疫赎,直接使用變量。

  3. 讓元素脫離動畫流:拖放代理

    • 使用絕對定位頁面上的動畫元素碎节,將其脫離文檔流捧搞。
    • 讓元素動起來,這時會臨時覆蓋部分頁面,只會發(fā)生小規(guī)模重繪胎撇。
    • 當(dāng)動畫結(jié)束時恢復(fù)定位介粘,從而只會下移一次文檔的其他元素。
  4. 在元素很多時晚树,避免使用:hover

批量修改DOM

關(guān)鍵:“離線”操作DOM樹姻采,使用緩存,減少訪問布局信息的次數(shù)爵憎。
策略:

  1. 使元素脫離文檔流
    • 隱藏元素(display:none)慨亲,應(yīng)用修改,重新顯示宝鼓。
    • 使用文檔片段在當(dāng)前DOM之外構(gòu)建一個子樹(document.createDocumentFragment())刑棵,再把它拷貝回文檔。(推薦)
    • 將原始元素拷貝到一個脫離文檔流的節(jié)點中愚铡,修改副本蛉签,完成后再替換原始元素。
  2. 對其應(yīng)用多重改變
  3. 把元素帶回文檔中

事件委托

之前寫過一篇<理解DOM事件處理程序和事件委托>的文章茂附,涉及事件模式的基本概念正蛙、事件流督弓、事件委托的實現(xiàn)等的闡述营曼,如果大家對以上概念有所遺忘,歡迎點擊鏈接查看原文愚隧。

每綁定一個事件處理器都會加重頁面負擔(dān)蒂阱、延長執(zhí)行時間、消耗更多的內(nèi)存(因為瀏覽器會跟蹤每個事件處理器)狂塘。

一個優(yōu)雅的策略就是利用事件委托录煤。

可以將冗長的瀏覽器兼容性代碼移入可重用的類庫:

  • 訪問事件對象,判斷事件源
  • 取消文檔樹中的冒泡
  • 阻止默認動作

四荞胡、算法和流程控制

大部分性能問題的來源是低效的算法或工具編寫出的糟糕代碼妈踊。

循環(huán)

代碼執(zhí)行的大部分消耗在循環(huán)

JS循環(huán)的類型:

  1. for循環(huán)


    for語句執(zhí)行流程

注:for循環(huán)初始化中var語句會創(chuàng)建一個函數(shù)級的變量泪漂,應(yīng)盡可能使用ES6中的let語句定義循環(huán)級變量廊营。

  1. while 循環(huán):和for類似,是最簡單的前測循環(huán)
  2. do-while 循環(huán):唯一的后測循環(huán)萝勤,循環(huán)體至少運行一次露筒。
  3. for-in 循環(huán):枚舉任何對象的屬性名key
  4. for-of 循環(huán):ES6新特性,枚舉任何對象的值value

拓展知識:for-in 和 for-of 區(qū)別

所返回的屬性:

  1. 對象的實例屬性
  2. 從原型鏈中繼承的屬性

循環(huán)性能:for-in 明顯慢

由于每次操作會同時搜索實例和原型屬性敌卓,查詢散列鍵慎式,會產(chǎn)生更多開銷。所以,除了明確需要迭代一個屬性數(shù)量未知的對象瘪吏,其他情況應(yīng)避免使用for-in癣防。

若其他循環(huán)的性能都差不多,其實只有兩個因素可以提升整體性能:

  1. 減少每次迭代的工作量:限制循環(huán)中的耗時操作總數(shù)
    • 最小化屬性查找
      關(guān)鍵:減少對象成員及數(shù)組項的查找次數(shù)
      策略:只查找一次屬性肪虎,并把值存到一個局部變量中劣砍。例如:var len = items.length;
    • 倒序循環(huán)
      通常,數(shù)組項的順序與所要執(zhí)行的任務(wù)無關(guān)扇救。倒序循環(huán)是編程語言中一種通用的性能優(yōu)化方式刑枝。

當(dāng)循環(huán)復(fù)雜度為O(n)時,減少每次迭代的工作量是最有效的迅腔。當(dāng)復(fù)雜度大于O(n)装畅,建議著重減少迭代次數(shù)。

  1. 減少迭代的次數(shù)
    達夫設(shè)備(Duff's Device):循環(huán)體展開技術(shù)沧烈,一次迭代中實際執(zhí)行了多次迭代的操作掠兄。

迭代數(shù)超過1000,使用 Duff's Device 的執(zhí)行效率將明顯提升锌雀。

基于函數(shù)的迭代 forEach() 明顯慢

原因:對每個數(shù)組項調(diào)用外部方法所帶來的額外開銷蚂夕。

條件語句

if-else 對比 switch
基于測試條件的數(shù)量選擇:條件數(shù)量越大,越傾向于使用switch腋逆,易讀性強且速度快婿牍。

大多數(shù)語言對 switch 語句的實現(xiàn)都采用了 branch table(分支表)索引進行優(yōu)化。

優(yōu)化 if-else

  1. 最小化到達正確分支前所需條件判斷的次數(shù)
    策略:條件語句按照從大概率到小概率的順序排列
  2. 把 if-else 組織成一系列嵌套的if-else 語句
    策略:二分法把值域分成一系列區(qū)間惩歉,逐步縮小范圍等脂。
    適用范圍:有多個值域需要測試。
    查找表
    當(dāng)條件語句數(shù)量很大或有大量散離值需要測試時撑蚌,使用數(shù)組普通對象構(gòu)建查找表訪問數(shù)據(jù)比較快上遥。

優(yōu)點:當(dāng)單個鍵和單個值之間存在邏輯映射時,隨著候選值增加争涌,幾乎不產(chǎn)生額外開銷粉楚。

遞歸

傳統(tǒng)算法的遞歸實現(xiàn):階層函數(shù)
潛在問題;

  1. 假死
    策略:為了安全在瀏覽器工作,可以迭代和Memoization結(jié)合使用亮垫。
  2. 瀏覽器調(diào)用棧大小限制 Call stack size limites
    當(dāng)超過最大調(diào)用棧容量時模软,瀏覽器會報錯,可以用try-catch定位包警。
    策略:ES6中使用尾遞歸就不會發(fā)生棧溢出撵摆,相對節(jié)省性能。

五害晦、字符串和正則表達式

字符串連接

方法 示例
The + operator str = "a" + "b" + "c";
The += operator str = "a"; str += "b"; str += "c";
array.join() str = ["a", "b", "c"].join("");
string.concat() str = "a"; str = str.concat("b","c");
轉(zhuǎn)義字符"" 在每一行的最后特铝,都加上轉(zhuǎn)義斜線 \
使用es6模版字符串 使用鍵盤1左邊的字符 ` 拼接

字符串連接優(yōu)化

str += 'zhu' + 'yue'; //2個以上的字符串拼接暑中,會在內(nèi)存中產(chǎn)生臨時字符串
str = str + 'zhu' + 'yue'; //推薦,直接附加內(nèi)容給str鲫剿,提速10%~40% 

瀏覽器合并字符串時分配的方法:除IE外鳄逾,為表達式左側(cè)的字符串分配更多的內(nèi)存,然后簡單地將第二個字符串拷貝至它的末尾灵莲。

正則表達式優(yōu)化

基本概念:正則表達式
注意避免:回溯失控

使用正則表達式和倒序循環(huán)可以簡單實現(xiàn)trim方法雕凹,去首尾空白。

優(yōu)化正則表達式的策略:

  1. 具體化分隔符之間的字符串匹配模式
  2. 使用預(yù)查和反向引用的模擬原子組
  3. 避免嵌套量詞與回溯失控
  4. 關(guān)注如何讓匹配更快失敗
  5. 以簡單必需的字元開始
  6. 使用量詞模式政冻,使它們后面的字元互斥
  7. 較少分支數(shù)量枚抵,縮小分支范圍
  8. 把正則表達式賦值給變量并重用
  9. 化繁為簡

何時不使用正則表達式

  1. 在特定位置上提取并檢查字符串的值:slice、substr明场、substring
  2. 查找特定字符串位置汽摹,或者判斷它們是否存在:indexOf、lastIndexOf

六苦锨、快速響應(yīng)的用戶界面

Web Workers 引入了一個接口逼泣,能使代碼運行且不占用瀏覽器線程的時間。

Worker的運行環(huán)境:

  • 一個 navigator 對象舟舒,只包括四個屬性:appName拉庶、appVersion、user Agent 和 platform
  • 一個 location 對象(與window.location 相同秃励,不過所有屬性都是只讀的)
  • 一個 importScripts() 方法氏仗,用來加載 Worker 所用到的外部 JavaScript 文件
  • 所有的 ECMAScript 對象
  • XMLHTTPRequest 構(gòu)造器
  • setTimeout() 和 setInterval() 方法
  • 一個 close() 方法,可以立即停止 Worker 運行莺治。

Web Workers 實際應(yīng)用

Web Workers 適用于:

  1. 處理純數(shù)據(jù)
  2. 與瀏覽器無關(guān)的長時間運行腳本
  3. 編碼/解碼大字符串
  4. 復(fù)雜數(shù)學(xué)運算廓鞠,如:圖像和視頻
  5. 大數(shù)組排序

例子:解析一個很大的JSON字符串

var worker = new Worker("jsonParser.js");
//數(shù)據(jù)就位時帚稠,調(diào)用事件處理器
worker.onmessage = function (event) {
    //JSON結(jié)構(gòu)被回傳回來
    var jsonData = event.data;
    //使用JSON結(jié)構(gòu)
    evaluateData(jsonData);
};
//傳入要解析的大段JSON字符串
worker.postMessage(jsonText);

jsonParser.js文件中 Worker 中負責(zé)解析JSON的代碼:

//當(dāng)JSON數(shù)據(jù)存在時谣旁,該事件處理器會被調(diào)用
self.onmessage = function (event) {
    //JSON字符串由event.data傳入
    var jsonText = event.data;
    //解析
    var jsonData = JSON.parse(jsonText);
    //回傳結(jié)果
    self.postMessage(jsonData);
}

超過100毫秒的處理過程,應(yīng)該考慮 Worker 方案滋早。

七榄审、AJAX

常常使用XMLHttpRequest(XHR)、Dynamic script tag insertion杆麸、multipart XHR技術(shù)向服務(wù)器請求數(shù)據(jù)搁进。

XMLHttpRequest:可以參考之前寫過的文章 用原生JS封裝AJAX
Dynamic script tag insertion:可以跨域請求數(shù)據(jù)
multipart XHR:將服務(wù)端資源打包成約定好的字符串分割的長字符串,并發(fā)送到客戶端昔头。

數(shù)據(jù)格式:JSON

此章節(jié)優(yōu)化主要是有效的利用瀏覽器緩存饼问,還有本章沒有提及的現(xiàn)在逐漸開始流行的 fetch API也值得討論。

八揭斧、編程實踐

  1. 避免雙重求值莱革,即在JavaScript代碼中執(zhí)行另一段JavaScript代碼,是JavaScript運行期性能優(yōu)化的關(guān)鍵。
  2. 使用 Object/Array 直接量
  3. 通過延遲加載和條件預(yù)加載盅视,避免重復(fù)工作
  4. 使用語言中速度快的部分捐名,如:位操作(& | ^ ~)、原生方法

九闹击、構(gòu)建并部署高性能JavaScript應(yīng)用

構(gòu)建和部署的過程對基于js的web應(yīng)用的性能有著巨大影響镶蹋。這個過程中最重要的步驟有:

  1. 使用Gzip合并、壓縮js文件赏半,能夠減少約70%的體積贺归。
  2. 通過正確設(shè)置HTTP響應(yīng)頭來緩存js文件,通過向文件名增加時間戳來避免緩存問題断箫。
  3. 使用CDN提供js文件牧氮;CDN不僅可以提升性能,也幫助管理文件的壓縮與緩存瑰枫。
  4. 使用Webpack構(gòu)建踱葛。

拓展:前端構(gòu)建工具的發(fā)展

十、工具

主要分析方面:

  1. 性能分析
  2. 網(wǎng)絡(luò)分析

總結(jié)

JavaScript 在不斷發(fā)展和擴充它的邊界光坝,我們也要不斷學(xué)習(xí)大量的優(yōu)化技術(shù)和方法尸诽。當(dāng)把這些策略應(yīng)用在項目中時,將會看到性能的明顯提升盯另,這也就是細節(jié)決定成敗性含。

最后,培養(yǎng)和保持良好的開發(fā)習(xí)慣鸳惯,對于個人發(fā)展和團隊合作都是很有必要的商蕴,推薦閱讀《高性能JavaScript》這本小薄書。??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芝发,一起剝皮案震驚了整個濱河市绪商,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌辅鲸,老刑警劉巖格郁,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異独悴,居然都是意外死亡例书,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門刻炒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來决采,“玉大人,你說我怎么就攤上這事坟奥∈鞑t!?“怎么了暂幼?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長移迫。 經(jīng)常有香客問我旺嬉,道長,這世上最難降的妖魔是什么厨埋? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任邪媳,我火速辦了婚禮,結(jié)果婚禮上荡陷,老公的妹妹穿的比我還像新娘雨效。我一直安慰自己,他們只是感情好废赞,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布徽龟。 她就那樣靜靜地躺著,像睡著了一般唉地。 火紅的嫁衣襯著肌膚如雪据悔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天耘沼,我揣著相機與錄音极颓,去河邊找鬼。 笑死群嗤,一個胖子當(dāng)著我的面吹牛菠隆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播狂秘,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼骇径,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了者春?” 一聲冷哼從身側(cè)響起破衔,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎碧查,沒想到半個月后运敢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體校仑,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡忠售,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了迄沫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稻扬。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖羊瘩,靈堂內(nèi)的尸體忽然破棺而出泰佳,到底是詐尸還是另有隱情盼砍,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布逝她,位于F島的核電站浇坐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏黔宛。R本人自食惡果不足惜近刘,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望臀晃。 院中可真熱鬧觉渴,春花似錦、人聲如沸徽惋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽险绘。三九已至踢京,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間宦棺,已是汗流浹背漱挚。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留渺氧,地道東北人旨涝。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像侣背,于是被迫代替她去往敵國和親白华。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5贩耐? 答:HTML5是最新的HTML標(biāo)準(zhǔn)弧腥。 注意:講述HT...
    kismetajun閱讀 27,422評論 1 45
  • 關(guān)于前端性能優(yōu)化問題詳解 出處:http://segmentfault.com/blogs 前端性能優(yōu)化指南 AJ...
    bennnnn閱讀 1,572評論 2 4
  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J的外補...
    _Yfling閱讀 13,728評論 1 92
  • AJax 優(yōu)化 緩存 Ajax 請求盡量使用GET, 僅取決于cookie數(shù)量 Cookie 優(yōu)化 減少Cooki...
    KeKeMars閱讀 9,326評論 5 89
  • 前端性能優(yōu)化資料整理 頁面性能差的直接后果是用戶需要等待潮太,而等待管搪,尤其是不確定要多長時間的等待會給用戶帶來焦慮,為...
    飄零之雪閱讀 791評論 2 3