寫出高效能javascript(1)—-三個習慣

來源:互聯網
上載者:User

  做了這麼久的前端工程師,總被朋友問到怎麼寫出高效能的javascript,那麼我今天就來簡單總結下,其實js本身是沒有什麼效能問題的,所謂的記憶體泄露,也主要針對於IE6,IE7,而IE7的記憶體泄露問題也並不嚴重,這裡不討論瀏覽器造成的記憶體泄露問題,我們只討論,養成什麼樣的書寫習慣能夠寫出,高效率高效能的js。

     在這裡我總結了三個書寫js的習慣,然後分別針對執行效率,記憶體問題,安全等各個方面綜合分析要養成這三個習慣的原因。

    1.盡量使用局部變數:

  局部變數的建立和訪問都是特別廉價快捷的,而使用全域變數的話,js對全域變數的調用實際上是對GLOBAL對象的尋找引用,效能低下。 而局部變數則是直接建立於當前範圍,不需要有尋找引用的過程。不單單是當前範圍,包括閉包裡的局部變數訪問,都是很快的。不過,這個過程帶來的最佳化是需要龐大的js程式長時間的運行才能體現出的。

下面通過細化js解析過程來理解下:

     一個變數具體是局部變數還是全域變數,局部變數的話是在哪層閉包裡,是第幾個變數,在編譯的時候就已經確定了,重複的var聲明並不會影響js的執行效率,js執行時,如果是局部變數則會直接在向記憶體位址裡取用,而全域變數則是對象訪問,顯然局部變數在效率上要最佳化的多。

  但是,不是任何時候局部變數都是最佳化的。

  例如,當一個變數是一個運算式或者一個尋找dom節點的過程等時,變數的取用中就帶有了尋找和計算過程,這樣如果計算次數比較多,用全域變數則可以一次性的固化結果,而使用局部變數反而需要多次計算尋找,而影響了效率了。

  總結:

  當然,以上的資料僅僅只對js代碼的執行效率而言,在具體應用中,我仍然推薦大家盡量使用局部變數。因為,js的一個重要的編程理念就是不要汙染全域對象,全域對象可能被不同的模組(甚至頁面上的廣告)訪問,在上面存放資料、函數會有不可預期的後果。所以,我們要靈活使用全域對象和局部變數。

   2.及時釋放回呼函數,解除事件綁定。

  上面一個習慣,主要針對於執行效率問題,而這個習慣則是針對記憶體泄露的問題了。除了古老瀏覽器本身的bug造成的記憶體泄露外,錯誤的書寫js代碼也會引起記憶體泄露的問題。

  首先,有如下代碼解釋下這句話的意思:

1 img.onload = function () {2     img.onload = img.onerror = null;3 }4 $(...).on('keyup', function(e){5     $().off(e);6 })

  那這麼做有什麼好處呢,那麼我們看下下面的情況:

   比如一個div的keyup和click事件。如果keyup事件引用了div,div又引用著click,那麼keyup就會引用click,如果click引用另一個div的keyup,就會導致記憶體泄露,解除綁定keyup或者click任何一者都會消除記憶體泄露。  而如果不及時釋放回呼函數,亦有可能發生以上的問題。  上面那段話是不是邏輯很複雜呢^ ^,總之養成這個習慣是不會錯的,那就是 及時釋放回呼函數,解除事件綁定。

 3.及時清除引用。

     這個習慣也是針對於記憶體泄露問題,我們先看看以下代碼:

 1 <!doctype html> 2 <html> 3 <head> 4     <title>Memory leak demo</title> 5 </head> 6 <body> 7     <a href="javascript:;">Click me</a> 8 </body> 9 <script src="jquery-1.8.0.js"></script><script>10     $('a').click(function callback(e) {11         $(this).remove();12         $('<a href="javascript:;">Click me</a>').appendTo(document.body).click(function(e2){13             e2.leak = e;14             callback.call(this, e2);15         });16         17         var current = e, n = 0;18         while(current.leak){19             current = current.leak;20             n++;21         }22         console.log('leaked: ' + n);23         //e = null;24     });25 </script>26 </html>

  這是段代碼在不停的替換頁面中的a標籤,並且為新的a標籤綁定clcik事件,在事件的回呼函數中,引用了上一個事件的e,導致了原本的a標籤即使已經被remove也無法被釋放,仍然儲存在記憶體裡。隨著使用者click次數的增多,記憶體泄露問題也會越來越嚴重。

   所以這個時候,我們就要記得及時清除引用,這段代碼的記憶體泄露問題是由於事件對象e引起的,在23行,去掉注釋後,e = null 釋放了內層函數對外層函數的變數e指向的對象的引用,使得e以及它引用的dom節點能被釋放,記憶體泄露問題也就得以解決了。

 

       當然,想寫出高效能的js,還有很多可以仔細研究的地方,而上面的三個習慣是可以在日常的編碼中養成的,也沒有什麼替換成本。還有很多良好的習慣,比如減少函數引用,盡量少使用閉包,等,想做到這些方式可能需要較高的替換成本,如果有機會以後再與大家分享吧~。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.