最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Web性能優(yōu)化系列 10個提升JavaScript性能的技巧

 更新時間:2016年09月27日 16:29:18   投稿:mdxy-dxy  
Javascript 性能優(yōu)化絕不是一種書面的技術,Nicholas 的技術演進列出了10條建議,幫助你寫出高效的 JS 代碼

Nicholas Zakas是一位 JS 大師,Yahoo! 首頁的前端主程。他是《高性能 Javascript》的作者,這本書值得每個程序員去閱讀。

當談到 JS 性能的時候,Zakas差不多就是你要找的,2010年六月他在Google Tech Talk發(fā)表了名為《Speed Up Your Javascript》的演講。

但 Javascript 性能優(yōu)化絕不是一種書面的技術,Nicholas 的技術演進列出了10條建議,幫助你寫出高效的 JS 代碼。

1. 定義局部變量

當一個變量被引用的時候,JavaScript將在作用域鏈中的不同成員中查找這個變量。作用域鏈指的是當前作用于下可用變量的集合,它在各種主流瀏覽器中至少包含兩個部分:局部變量的集合和全局變量的集合。

簡單地說,如果JavaScript引擎在作用域鏈中搜索的深度越大,那么操作也就會消耗更多的時間。引擎首先從 this 開始查找局部變量,然后是函數參數、本地定義的變量,最后遍歷所有的全局變量。

因為局部變量在這條鏈的起端,所以查找局部變量總是比查找全局變量要塊。所以當你想要不止一次地使用一個全局變量的時候,你應該將它定義成局部變量,就像這樣:

var blah = document.getElementById('myID'),
blah2 = document.getElementById('myID2');

改寫成

var doc = document,
blah = doc.getElementById('myID'),
blah2 = doc.getElementById('myID2');

2. 不要使用 with() 語句

這是因為 with() 語句將會在作用域鏈的開始添加額外的變量。額外的變量意味著,當任何變量需要被訪問的時候,JavaScript引擎都需要先掃描with()語句產生的變量,然后才是局部變量,最后是全局變量。
So with() essentially gives local variables all the performance drawbacks of global ones, and in turn derails Javascript optimization. 因此with()語句同時給局部變量和全局變量的性能帶來負面影響,最終使我們優(yōu)化JavaScript性能的計劃破產。

3. 小心使用閉包

雖然你可能還不知道“閉包”,但你可能在不經意間經常使用這項技術。閉包基本上被認為是JavaScript中的new,當我們定義一個即時函數的時候,我們就使用了閉包,比如:

 document.getElementById('foo').onclick = function(ev) { };

閉包的問題在于:根據定義,在它們的作用域鏈中至少有三個對象:閉包變量、局部變量和全局變量。這些額外的對象將會導致第1和第2個建議中提到的性能問題。

但是我認為Nicholas并不是要我們因噎廢食,閉包對于提高代碼可讀性等方面還是非常有用的,只是不要濫用它們(尤其在循環(huán)中)。

4. 對象屬性和數組元素的速度都比變量慢

談到JavaScript的數據,一般來說有4種訪問方式:數值、變量、對象屬性和數組元素。在考慮優(yōu)化時,數值和變量的性能差不多,并且速度顯著優(yōu)于對象屬性和數組元素。
因此當你多次引用一個對象屬性或者數組元素的時候,你可以通過定義一個變量來獲得性能提升。(這一條在讀、寫數據時都有效)
雖然這條規(guī)則在絕大多數情況下是正確的,但是Firefox在優(yōu)化數組索引上做了一些有意思的工作,能夠讓它的實際性能優(yōu)于變量。但是考慮到數組元素在其他瀏覽器上的性能弊端,還是應該盡量避免數組查找,除非你真的只針對于火狐瀏覽器的性能而進行開發(fā)。

5. 不要在數組中挖得太深

另外,程序員應該避免在數組中挖得太深,因為進入的層數越多,操作速度就越慢。
簡單地說,在嵌套很多層的數組中操作很慢是因為數組元素的查找速度很慢。試想如果操作嵌套三層的數組元素,就要執(zhí)行三次數組元素查找,而不是一次。
因此如果你不斷地引用 foo.bar, 你可以通過定義 var bar = foo.bar 來提高性能。

6. 避免 for-in 循環(huán)(和基于函數的迭代)

這是另一條非常教條的建議:不要使用for-in循環(huán)。
這背后的邏輯非常直接:要遍歷一個集合內的元素,你可以使用諸如for循環(huán)、或者do-while循環(huán)來替代for-in循環(huán),for-in循環(huán)不僅僅可能需要遍歷額外的數組項,還需要更多的時間。
為了遍歷這些元素,JavaScript需要為每一個元素建立一個函數,這種基于函數的迭代帶來了一系列性能問題:額外的函數引入了函數對象被創(chuàng)建和銷毀的上下文,將會在作用域鏈的頂端增加額外的元素。

7. 在循環(huán)時將控制條件和控制變量合并起來

提到性能,在循環(huán)中需要避免的工作一直是個熱門話題,因為循環(huán)會被重復執(zhí)行很多次。所以如果有性能優(yōu)化的需求,先對循環(huán)開刀有可能會獲得最明顯的性能提升。
一種優(yōu)化循環(huán)的方法是在定義循環(huán)的時候,將控制條件和控制變量合并起來,下面是一個沒有將他們合并起來的例子:
 for ( var x = 0; x < 10; x++ ) {
};

當我們要添加什么東西到這個循環(huán)之前,我們發(fā)現(xiàn)有幾個操作在每次迭代都會出現(xiàn)。JavaScript引擎需要:

#1:檢查 x 是否存在
#2:檢查 x 是否小于 0 (譯者注:我猜這里是作者的筆誤)
#3:使 x 增加 1

然而如果你只是迭代元素中的一些元素,那么你可以使用while循環(huán)進行輪轉來替代上面這種操作:

var x = 9;
do { } while( x-- );

如果你想更深入地了解循環(huán)的性能,Zakas提供了一種高級的循環(huán)優(yōu)化技巧,使用異步進行循環(huán)(碉堡了!)

8. 為HTML集合對象定義數組

JavaScript使用了大量的HTML集合對象,比如 document.forms,document.images 等等。通常他們被諸如 getElementsByTagName、getElementByClassName 等方法調用。

由于大量的DOM selection操作,HTML集合對象相當的慢,而且還會帶來很多額外的問題。正如DOM標準中所定義的那樣:“HTML集合是一個虛擬存在,意味著當底層文檔被改變時,它們將自動更新?!边@太可怕了!

盡管集合對象看起來跟數組很像,他們在某些地方卻區(qū)別很大,比如對于特定查詢的結果。當對象被訪問進行讀寫時,查詢需要重新執(zhí)行來更新所有與對象相關的組分,比如 length。

HTML集合對象也非常的慢,Nicholas說好像在看球的時候對一個小動作進行60倍速慢放。另外,集合對象也有可能造成死循環(huán),比如下面的例子:

var divs = document.getElementsByTagName('div');
 
for (var i=0; i < divs.length; i++ ) {
  var div = document.createElement("div"); 
  document.appendChild(div);
}

這段代碼造成了死循環(huán),因為 divs 表示一個實時的HTML集合,并不是你所期望的數組。這種實時的集合在添加 <div> 標簽時被更新,所以i < div.length 永遠都不會結束。

解決這個問題的方法是將這些元素定義成數組,相比只設置 var divs = document.getElementsByTagName(‘div') 稍微有點麻煩,下面是Zakas提供的強制使用數組的代碼:

function array(items) {
  try {
    return Array.prototype.concat.call(items);
  } catch (ex) {
 
    var i    = 0,
      len   = items.length,
      result = Array(len);
 
    while (i < len) {
      result[i] = items[i];
      i++;
    }
 
    return result;
  }
}
 
var divs = array( document.getElementsByTagName('div') );
 
for (var i=0l i < divs.length; i++ ) {
  var div = document.createElement("div"); 
  document.appendChild(div);
}

9. 不要碰DOM!

不使用DOM是JavaScript優(yōu)化中另一個很大的話題。經典的例子是添加一系列的列表項:如果你把每個列表項分別加到DOM中,肯定會比一次性加入所有列表項到DOM中要慢。這是因為DOM操作開銷很大。
Zakas對這個進行了細致的講解,解釋了由于回流(reflow)的存在,DOM操作是非常消耗資源的?;亓魍ǔ1焕斫鉃闉g覽器重新選渲染DOM樹的處理過程。比如說,如果你用JavaScript語句改變了一個div的寬度,瀏覽器需要重繪頁面來適應變化。
任何時候只要有元素被添加到DOM樹或者從DOM樹移除,都會引發(fā)回流。使用一個非常方便的JavaScript對象可以解決這個問題——documentFragment,我并沒有使用過,但是在Steve Souders也表示同意這種做法之后我感覺更加肯定了。
DocumentFragment 基本上是一種瀏覽器以非可視方式實現(xiàn)的類似文檔的片段,非可視化的表現(xiàn)形式帶來了很多優(yōu)點,最主要的是你可以在 documentFragment 中添加任何結點而不會引起瀏覽器回流。

10. 修改CSS類,而不是樣式


你也許聽說過:修改CSS類必直接修改樣式會更高效。這歸結于回流帶來的另一個問題:當布局樣式發(fā)生改變時,會引發(fā)回流。
布局樣式意味著任何影響改變布局的變化都會強制引起瀏覽器回流。比如寬度、高度、字號、浮動等。
但是別誤會我的意思,CSS類并不會避免回流,但是可以將它的影響最小化。相比每次修改樣式都會引起回流,使用CSS類一次修改多個樣式,只需要承擔一次回流帶來的消耗。
因此在修改多個布局樣式的時候,使用CSS類來優(yōu)化性能是明智的選擇。另外如果你需要在運行時定義很多歌CSS類,在DOM上添加樣式結點也是不錯的選擇。

總結

Nicholas C. Zakas 是JavaScript界的權威。在寫這篇文章的時候,我發(fā)現(xiàn)我引用的很多文章也是他寫的——因為太難找到其他更好的文章。
Zakas的技術演進非常棒,他解釋了很多JavaScript優(yōu)化規(guī)則的原因,我已奉為圣經。

相關文章

  • 理解javascript中Map代替循環(huán)

    理解javascript中Map代替循環(huán)

    這篇文章主要幫助大家理解javascript中Map代替循環(huán),感興趣的小伙伴們可以參考一下
    2016-02-02
  • JS window對象簡單操作完整示例

    JS window對象簡單操作完整示例

    這篇文章主要介紹了JS window對象簡單操作,結合完整實例形式分析了JavaScript Window對象各種常見提示框、彈出窗口及時間相關操作技巧,需要的朋友可以參考下
    2020-01-01
  • 淺談JavaScript 中的延遲加載屬性模式

    淺談JavaScript 中的延遲加載屬性模式

    改善性能的最好方法之一是避免重復兩次相同的工作。因此,只要可以緩存結果供以后使用,就可以加快程序的速度。延遲加載屬性模式技術使任何屬性都可以成為緩存層以提高性能。這里說到的延遲加載屬性模式就是利用的訪問器屬性,將計算昂貴的操作推遲到需要時再使用
    2021-06-06
  • JavaScript仿京東放大鏡效果

    JavaScript仿京東放大鏡效果

    這篇文章主要為大家詳細介紹了JavaScript仿京東放大鏡效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • ES6 javascript中class類的get與set用法實例分析

    ES6 javascript中class類的get與set用法實例分析

    這篇文章主要介紹了ES6 javascript中class類的get與set用法,結合具體實例形式分析了ES6中類的get與set關鍵字使用方法,需要的朋友可以參考下
    2017-10-10
  • 微信小程序自定義tabbar欄實現(xiàn)過程講解

    微信小程序自定義tabbar欄實現(xiàn)過程講解

    tabBar相對而言用的還是比較多的,但是用起來并沒有難,下面這篇文章主要給大家介紹了關于微信小程序全局配置之tabBar的相關資料,文中通過圖文以及示例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-02-02
  • 支付寶小程序從手動埋點到自動埋點的實現(xiàn)過程

    支付寶小程序從手動埋點到自動埋點的實現(xiàn)過程

    埋點的意思是在你想要的數據節(jié)點出進行設置,可以方便進行采集,下面這篇文章主要給大家介紹了關于支付寶小程序從手動埋點到自動埋點的相關資料,需要的朋友可以參考下
    2022-03-03
  • js實現(xiàn)canvas圖片與img圖片的相互轉換的示例

    js實現(xiàn)canvas圖片與img圖片的相互轉換的示例

    本篇文章主要介紹了js實現(xiàn)canvas圖片與img圖片的相互轉換的示例,具有一定的參考價值,有興趣的可以了解一下
    2017-08-08
  • js實現(xiàn)簡易的英漢詞典

    js實現(xiàn)簡易的英漢詞典

    這篇文章主要為大家詳細介紹了js實現(xiàn)簡易的英漢詞典,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • JavaScript惰性載入函數實例分析

    JavaScript惰性載入函數實例分析

    這篇文章主要介紹了JavaScript惰性載入函數,結合實例形式分析了JavaScript惰性載入函數的概念、原理、實現(xiàn)方法及相關操作注意事項,需要的朋友可以參考下
    2019-03-03

最新評論

宣城市| 高安市| 涟源市| 徐汇区| 长白| 宁南县| 高平市| 丰顺县| 化德县| 南漳县| 乳山市| 永川市| 西藏| 潞西市| 广平县| 高密市| 揭东县| 昌江| 城口县| 巴东县| 北安市| 皋兰县| 塘沽区| 伊金霍洛旗| 共和县| 东乡族自治县| 二手房| 渝中区| 绵竹市| 谢通门县| 平遥县| 广水市| 西乌| 长岛县| 兰坪| 赤壁市| 辛集市| 南漳县| 子洲县| 平乐县| 东乡族自治县|