在使用垃圾回收的程式設計環境中,開發者通常無須關心記憶體管理。不過,JavaScript執行在一個記憶體管理與垃圾回收都很特殊的環境。分配給瀏覽器的記憶體通常比分配給桌面軟體的要少很多,分配給移動瀏覽器的就更少了。這更多出於安全考慮而不是別的,就是為了避免執行大量JavaScript的網頁耗盡系統記憶體而導致作業系統崩潰。這個記憶體限制不僅影響變數分配,也影響呼叫棧以及能夠同時在一個執行緒中執行的語句數量。將記憶體佔用量保持在一個較小的值可以讓頁面效能更好。最佳化內 存佔用的最佳手段就是保證在執行程式碼時只儲存必要的資料。如果數 據不再必要,那麼把它設定為 null ,從而釋放其引用。這也可以叫 作解除引用。這個建議最適合全域性變數和全域性物件的屬性。區域性變數 在超出作用域後會被自動解除引用
1、透過const和let宣告提升效能
因為 const 和 let 都以塊(而非函式)為作用域,所以相比於使用 var ,使用這兩個新關鍵字可能會更早地讓垃圾回收程式介入,儘早回收應該回收的記憶體。在塊作用域比函式作用域更早終止的情況下,這就有可能發生。
如
function Article() { this.title = 'Inauguration Ceremony Features Kazoo Band';}let a1 = new Article();let a2 = new Article();a2.author = 'Jake';
此時兩個 Article 例項就會對應兩個不同的隱藏類。根據這種操作的頻率和隱藏類的大小,這有可能對效能產生明顯影響。解決方案就是避免JavaScript的“先建立再補充”(ready-fireaim)式的動態屬性賦值,並在建構函式中一次性宣告所有屬性。最佳化為
function Article(opt_author) { this.title = 'Inauguration Ceremony Features Kazoo Band'; this.author = opt_author;}let a1 = new Article();let a2 = new Article('Jake');
這樣,兩個例項基本上就一樣了(不考慮 hasOwnProperty 的返回值),因此可以共享一個隱藏類,從而帶來潛在的效能提升。function Article() { this.title = 'Inauguration Ceremony Features Kazoo Band'; this.author = 'Jake';}let a1 = new Article();let a2 = new Article();// 共享一個隱藏類,這樣,兩個例項基本上就一樣了(不考慮 hasOwnProperty 的返回值)delete a1.author;// 使用 delete 關鍵字會導致生成相同的隱藏類片段,既不再共享一個隱藏類// 在程式碼結束後,即使兩個例項使用了同一個建構函式,它們也不再共享一個隱藏類。// 動態刪除屬性與動態添屬性導致的後果一樣。a1.author=null// 最佳實踐是把不想要的屬性設定為 null 。這樣可以保持隱藏類不變和繼續共享,// 同時也能達到刪除引用值供垃圾回收程式回收的效果。
3、記憶體洩漏
例1、function setName() {name = 'Jake';}
此時,直譯器會把變數 name 當作 window 的屬性來建立(相當於 window.name = 'Jake' )。可想而知,在 window 物件上建立的屬性,只要 window 本身不被清理就不會消失。這個 問題很容易解決,只要在變數宣告前頭加上let、cont、var即可,這樣變數就會在函式執行完畢後離開作用域。例2、定時器的回撥透過閉包引用了外部變數let name = 'Jake';setInterval(() => { console.log(name);}, 100);
只要定時器一直執行,回撥函式中引用的 name 就會一直佔用記憶體。垃圾回收程式當然知道這一點,因而就不會清理外部變數。使用JavaScript閉包很容易在不知不覺間造成記憶體洩漏。
例3let outer = function () { let name = 'Jake'; return function () { return name; };};
這會導致分配給 name 的記憶體被洩漏。以上程式碼建立了一個內部閉包,只要 outer 函式存在就不能清理 name ,因為閉包一直在引用著它。假如 name 的內容很大(不止是一個小字串),那可能就是個大問題了。
四、靜態分配與物件池
注意 靜態分配是最佳化的一種極端形式。如果你的應用程式被垃圾回收嚴重地拖了後腿,可以利用它提升效能。但這種情況並不多見。大多數情況下,這都屬於過早最佳化,因此不用考慮。
最新評論