javascript
【读书笔记】《编写高效的JavaScript程序》
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??
看到一篇文章,http://www.csdn.net/article/2012-11-20/2811887-writing-fast-memory-efficient-javascript/2
里面有個(gè)網(wǎng)頁(yè)針對(duì) 原型鏈,模塊化,模塊化加緩存,進(jìn)行了比對(duì)測(cè)試:http://jsperf.com/prototypal-performance/12
測(cè)試用例及測(cè)試結(jié)果如下:(chrome下)
測(cè)試代碼如下:
<script>Benchmark.prototype.setup?=?function()?{Klass1?=?function()?{}Klass1.prototype.foo?=?function()?{log('foo');}Klass1.prototype.bar?=?function()?{log('bar');}Klass2?=?function()?{var?foo?=?function()?{log('foo');},bar?=?function()?{log('bar');};return?{foo:?foo,?bar:?bar}}var?FooFunction?=?function()?{log('foo');};var?BarFunction?=?function()?{log('bar');};Klass3?=?function()?{return?{foo:?FooFunction,?bar:?BarFunction}}}; </script>愚見(jiàn):
先不說(shuō)這個(gè)測(cè)試案例是否真能體現(xiàn)性能。只從代碼書(shū)寫(xiě)和學(xué)習(xí)過(guò)程來(lái)說(shuō)。
如果能摒棄一個(gè)function寫(xiě)完一整個(gè)功能的做法,進(jìn)入模塊化編程。這是個(gè)進(jìn)步。
再說(shuō)上述所謂緩存,其實(shí)就是給函數(shù)閉包加了一個(gè)引用,因?yàn)橐玫拇嬖?#xff0c;所以閉包不會(huì)按通常情況被銷毀。如果有人這樣寫(xiě),大量的全局變量,對(duì)于需要長(zhǎng)期維護(hù)更新的項(xiàng)目來(lái)說(shuō)這簡(jiǎn)直就是災(zāi)難。我自己就深受其害,而且是被自己所坑。絕對(duì)不能推廣這種做法。有了開(kāi)頭就沒(méi)結(jié)尾,養(yǎng)成習(xí)慣就難改了。(如果是在一個(gè)規(guī)模龐大前端依然成體系的公司,萬(wàn)一人家要求,還是不得不寫(xiě),不過(guò)這種情況下,就連命名都會(huì)有諸多規(guī)范和要求吧。)
最推薦的,自然是原型鏈的寫(xiě)法。不過(guò)真心表示需要根據(jù)項(xiàng)目需要和能力而為,否則寫(xiě)出來(lái)的東西簡(jiǎn)直就是慘不忍睹。不管怎樣,學(xué)習(xí)中。
-----------------------------------------------
原文摘錄如下:
Addy Osmani是谷歌公司Chrome團(tuán)隊(duì)中的一名程序開(kāi)發(fā)工程師。他是一位JavaScript愛(ài)好者,曾經(jīng)編寫(xiě)過(guò)一本開(kāi)放源碼方面的書(shū)籍《Learning JavaScript Design Patterns》以及《Developing Backbone Applications》。為Modernizr和jQuery社區(qū)貢獻(xiàn)了開(kāi)源項(xiàng)目,目前正在從事‘Yeoman’項(xiàng)目,旨在為開(kāi)發(fā)者提供一系列健壯的工具、程序庫(kù)和工作流,幫助他們快速構(gòu)建出漂亮、引人注目的Web應(yīng)用。本文作者將帶領(lǐng)大家探索高效編寫(xiě)代碼的測(cè)試驗(yàn)證方法。文章內(nèi)容如下:
JavaScript引擎包括Google V8(Chrome,Node)都是專為快速執(zhí)行大型JavaScript程序而設(shè)計(jì)的。在開(kāi)發(fā)過(guò)程中,如果你在乎內(nèi)存使用率和性能情況,那么你應(yīng)該會(huì)關(guān)心在用戶的瀏覽器中JavaScript引擎背后是怎么樣的。無(wú)論是V8、SpiderMonkey (Firefox)、Carakan (Opera)、Chakra (IE) 還是其他,有了它們可以幫助你更好的優(yōu)化應(yīng)用程序。
我們應(yīng)該時(shí)不時(shí)地詢問(wèn)自己:
我還能做些什么使代碼更加有效?
主流的JavaScript引擎做了哪些優(yōu)化?
什么是引擎無(wú)法優(yōu)化的,我能期待利用垃圾回收進(jìn)行清潔嗎?
當(dāng)涉及到編寫(xiě)高效的內(nèi)存和快速創(chuàng)建代碼時(shí)總會(huì)出現(xiàn)一些常見(jiàn)的弊端,在這篇文章中我們將探索高效編寫(xiě)代碼的測(cè)試驗(yàn)證方法。
一、JavaScript如何在V8中工作?
如果你對(duì)JS引擎沒(méi)有較深的了解,開(kāi)發(fā)一個(gè)大型Web應(yīng)用也沒(méi)啥問(wèn)題,就好比會(huì)開(kāi)車的人也只是看過(guò)引擎蓋而沒(méi)有看過(guò)車蓋內(nèi)的引擎一樣(這里將Web網(wǎng)頁(yè)比如成汽車)。Chrome瀏覽器是我的優(yōu)先選擇,這里我將談下V8的核心組件:
一個(gè)基本的編譯器,在代碼執(zhí)行前分析JavaScript、生成本地機(jī)器代碼而非執(zhí)行字節(jié)代碼或是簡(jiǎn)單的解釋,該段代碼之初不是高度優(yōu)化的。
V8用對(duì)象模型“表述”對(duì)象。在JavaScript中,對(duì)象是一個(gè)關(guān)聯(lián)數(shù)組,但是V8中,對(duì)象被“表述”為隱藏類,這種隱藏類是V8的內(nèi)部類型,用于優(yōu)化后的查找。
運(yùn)行時(shí)分析器監(jiān)視正在運(yùn)行的系統(tǒng)并優(yōu)化“hot”(活躍)函數(shù)。(比如,終結(jié)運(yùn)行已久的代碼)
通過(guò)運(yùn)行時(shí)分析器把優(yōu)化編譯器重新編譯和被運(yùn)行時(shí)分析器標(biāo)識(shí)為“hot”的代碼 ,這是一種有效的編譯優(yōu)化技術(shù),(例如用被調(diào)用者的主體替換函數(shù)調(diào)用的位置)。
V8支持去優(yōu)化,也就是說(shuō)當(dāng)你發(fā)現(xiàn)一些假設(shè)的優(yōu)化代碼太過(guò)樂(lè)觀,優(yōu)化編譯器可以退出已生成的代碼。
垃圾回收,了解它是如何工作的,如同優(yōu)化JavaScript一樣同等重要。
二、垃圾回收
垃圾回收是內(nèi)存管理的一種形式,它試圖通過(guò)將不再使用的對(duì)象修復(fù)從而釋放內(nèi)存占用率。垃圾回收語(yǔ)言(比如JavaScript)是指在JavaScript這種垃圾回收語(yǔ)言中,應(yīng)用程序中仍在被引用的對(duì)象不會(huì)被清除。手動(dòng)消除對(duì)象引用在大多數(shù)情況下是沒(méi)有必要的。通過(guò)簡(jiǎn)單地把變量放在需要它們的地方(理想情況下,盡可能是局部作用域,即它們被使用的函數(shù)里而不是函數(shù)外層),一切將運(yùn)作地很好。
在JavaScript中強(qiáng)制執(zhí)行垃圾回收是不取的,當(dāng)然,你也不會(huì)想這么做,因?yàn)槔厥者M(jìn)程被運(yùn)行時(shí)控制著,它知道什么時(shí)候才是適合清理代碼的最好時(shí)機(jī)。
1.“消除引用”的誤解(De-Referencing Misconceptions)
在JavaScript中回收內(nèi)存在網(wǎng)上引發(fā)了許多爭(zhēng)論,雖然它可以被用來(lái)刪除對(duì)象(map)中的屬性(key),但有部分開(kāi)發(fā)者認(rèn)為它可以用來(lái)強(qiáng)制“消除引用”。建議盡可能避免使用delete,在下面的例子中delete o.x 的弊大于利,因?yàn)樗淖兞薿的隱藏類,使它成為通用的慢對(duì)象。
var?o?=?{?x:?1?};?? delete?o.x;?//?true?? o.x;?//?undefined目的是為了在運(yùn)行時(shí)避免修改活躍對(duì)象的結(jié)構(gòu),JavaScript引擎可以刪除類似“hot”對(duì)象,并試圖對(duì)其進(jìn)行優(yōu)化。如果該對(duì)象的結(jié)果沒(méi)有太大改變,超過(guò)生命周期,刪除可能會(huì)導(dǎo)致其改變。
對(duì)于null是如何工作也是有誤解的。將一個(gè)對(duì)象引用設(shè)置為null,并沒(méi)有使對(duì)象變“空”,只是將它的引用設(shè)置為空而已。使用o.x= null比使用delete會(huì)更好些,但可能也不是很必要。
var?o?=?{?x:?1?};?? o?=?null;?? o;?//?null?? o.x?//?TypeError如果這個(gè)引用是最后一個(gè)引用對(duì)象,那么該對(duì)象可進(jìn)行垃圾回收;倘若不是,那么此方法不可行。注意,無(wú)論您的網(wǎng)頁(yè)打開(kāi)多久,全局變量不能被垃圾回收清理。
var?myGlobalNamespace?=?{};當(dāng)你刷新新頁(yè)面時(shí),或?qū)Ш降讲煌捻?yè)面,關(guān)閉標(biāo)簽頁(yè)或是退出瀏覽器,才可進(jìn)行全局清理;當(dāng)作用域不存在這個(gè)函數(shù)作用域變量時(shí),這個(gè)變量才會(huì)被清理,即該函數(shù)被退出或是沒(méi)有被調(diào)用時(shí),變量才能被清理。
經(jīng)驗(yàn)法則:
為了給垃圾回收創(chuàng)造機(jī)會(huì),盡可能早的收集對(duì)象,盡量不要隱藏不使用的對(duì)象。這一點(diǎn)主要是自動(dòng)發(fā)生,這里有幾點(diǎn)需要謹(jǐn)記:
正如之前我們提到的,手動(dòng)引用在合適的范圍內(nèi)使用變量是個(gè)更好的選擇,而不是將全局變量清空,只需使用不再需要的局部函數(shù)變量。也就是說(shuō)我們不要為清潔代碼而擔(dān)心。
確保移除不再需要的事件偵聽(tīng)器,尤其是當(dāng)DOM對(duì)象將要被移除時(shí)。
如果你正在使用本地?cái)?shù)據(jù)緩存,請(qǐng)務(wù)必清潔該緩存或使用老化機(jī)制來(lái)避免存儲(chǔ)那些不再使用的大量數(shù)據(jù)。
2.函數(shù)(Functions)
正如我們前面提到的垃圾回收的工作原理是對(duì)內(nèi)存堆中已經(jīng)死亡的或者長(zhǎng)時(shí)間沒(méi)有使用的對(duì)象進(jìn)行清除和回收。下面的例子能夠更好的說(shuō)明這一點(diǎn):
function?foo()?{?? var?bar?=?new?LargeObject();?? bar.someCall();??? }當(dāng)foo返回時(shí),bar自動(dòng)指向垃圾回收對(duì)象,這是因?yàn)闆](méi)被調(diào)用,這里我們將做個(gè)對(duì)比:
function?foo()?{??var?bar?=?new?LargeObject();??bar.someCall();??return?bar;?? }?? //?somewhere?else?? var?b?=?foo();這里有個(gè)調(diào)用對(duì)象且被一直調(diào)用著直到這個(gè)調(diào)用交給b(或是超出b范圍)。
3.閉包(Closures)
當(dāng)你看到一個(gè)函數(shù)返回到內(nèi)部函數(shù),該內(nèi)部函數(shù)可以訪問(wèn)外部函數(shù),即使外部函數(shù)正在被執(zhí)行。這基本上是一個(gè)封閉的,可以在特定的范圍內(nèi)設(shè)置變量的表達(dá)式。比如:
function?sum?(x)?{??function?sumIt(y)?{??return?x?+?y;??};??return?sumIt;?? }??//?Usage?? var?sumA?=?sum(4);?? var?sumB?=?sumA(3);?? console.log(sumB);?//?Returns?7在sum調(diào)用上下文中生成的函數(shù)對(duì)象(sumIt)是無(wú)法被回收的,它被全局變量(sumA)所引用,并且可以通過(guò)sumA(n)調(diào)用。
這里有個(gè)示例演示如何訪問(wèn)largeStr?
var?a?=?function?()?{??var?largeStr?=?new?Array(1000000).join('x');??return?function?()?{??return?largeStr;??};?? }();我們可以通過(guò)a():
var?a?=?function?()?{??var?smallStr?=?'x';??var?largeStr?=?new?Array(1000000).join('x');??return?function?(n)?{??return?smallStr;??};?? }();
此時(shí),我們不能訪問(wèn)了,因?yàn)樗抢厥盏暮蜻x者。
4.計(jì)時(shí)器(Timers)
最糟糕的莫過(guò)于在循環(huán)中泄露,或者在setTimeout()/setInterval()中,但這卻是常見(jiàn)的問(wèn)題之一。
var?myObj?=?{??callMeMaybe:?function?()?{??var?myRef?=?this;??var?val?=?setTimeout(function?()?{??console.log('Time?is?running?out!');??myRef.callMeMaybe();??},?1000);??}?? };
如果我們運(yùn)行:
myObj.callMeMaybe();在計(jì)時(shí)器開(kāi)始前,我們看到每一秒“時(shí)間已經(jīng)不多了”,這時(shí),我們將運(yùn)行:
myObj?=?null;三、當(dāng)心性能陷阱
除非你真正需要,否則永遠(yuǎn)不要優(yōu)化代碼。在V8中你能輕易的看到一些細(xì)微的基準(zhǔn)測(cè)試顯示比如N比M更佳,但是在真實(shí)的模塊代碼中或是在實(shí)際的應(yīng)用程序中測(cè)試,這些優(yōu)化所帶來(lái)的影響要比你想象中要小的多。
創(chuàng)建一個(gè)模塊,這里有三點(diǎn):
采用本地的數(shù)據(jù)源包含ID數(shù)值
繪制一個(gè)包含這些數(shù)據(jù)的表格
添加事件處理程序,當(dāng)用戶點(diǎn)擊的任何單元格時(shí)切換單元格的css class
如何存儲(chǔ)數(shù)據(jù)?如何高效的繪制表格并追加到DOM?怎樣處理表單上的事件?
注意:下面的這段代碼,千萬(wàn)不能做:
var?moduleA?=?function?()?{??return?{??data:?dataArrayObject,??init:?function?()?{??this.addTable();??this.addEvents();??},??addTable:?function?()?{??for?(var?i?=?0;?i?<?rows;?i++)?{??$tr?=?$('<tr></tr>');??for?(var?j?=?0;?j?<?this.data.length;?j++)?{??$tr.append('<td>'?+?this.data[j]['id']?+?'</td>');??}??$tr.appendTo($tbody);??}??},??addEvents:?function?()?{??$('table?td').on('click',?function?()?{??$(this).toggleClass('active');??});??}??};?? }();很簡(jiǎn)單,但是卻能把工作完成的很好。
請(qǐng)注意,直接使用DocumentFragment和本地DOM方法生成表格比使用jQuery更佳,事件委托通常比單獨(dú)綁定每個(gè)td更具備高性能。jQuery一般在內(nèi)部使用DocumentFragment,但是在這個(gè)例子中,通過(guò)內(nèi)循環(huán)調(diào)用代碼append() ,因此,無(wú)法在這個(gè)例子中進(jìn)行優(yōu)化,但愿這不是一個(gè)詬病,但請(qǐng)務(wù)必將代碼進(jìn)行基準(zhǔn)測(cè)試。
這里,我們通過(guò)opting for documentFragment提高性能,事件代理對(duì)簡(jiǎn)單的綁定是一種改進(jìn),可選的DocumentFragment也起到了助推作用。
var?moduleD?=?function?()?{??return?{??data:?dataArray,??init:?function?()?{??this.addTable();??this.addEvents();??},??addTable:?function?()?{??var?td,?tr;??var?frag?=?document.createDocumentFragment();??var?frag2?=?document.createDocumentFragment();??for?(var?i?=?0;?i?<?rows;?i++)?{??tr?=?document.createElement('tr');??for?(var?j?=?0;?j?<?this.data.length;?j++)?{??td?=?document.createElement('td');??td.appendChild(document.createTextNode(this.data[j]));??frag2.appendChild(td);??}??tr.appendChild(frag2);??frag.appendChild(tr);??}??tbody.appendChild(frag);??},??addEvents:?function?()?{??$('table').on('click',?'td',?function?()?{??$(this).toggleClass('active');??});??}??};??}();我們不妨看看其他提供性能的方法,也許你曾讀過(guò)使用原型模式或是使用JavaScript模板框架進(jìn)行高度優(yōu)化。但是使用這些僅針對(duì)可讀的代碼。此外,還有預(yù)編譯。我們一起來(lái)實(shí)踐下:
moduleG?=?function?()?{};??moduleG.prototype.data?=?dataArray;?? moduleG.prototype.init?=?function?()?{??this.addTable();??this.addEvents();?? };?? moduleG.prototype.addTable?=?function?()?{??var?template?=?_.template($('#template').text());??var?html?=?template({'data'?:?this.data});??$tbody.append(html);?? };?? moduleG.prototype.addEvents?=?function?()?{??$('table').on('click',?'td',?function?()?{??$(this).toggleClass('active');??});?? };??var?modG?=?new?moduleG();事實(shí)證明,選擇模板和原型并沒(méi)有給我們帶來(lái)多大好處。
四、V8引擎優(yōu)化技巧:
特定的模式會(huì)導(dǎo)致V8優(yōu)化產(chǎn)生故障。很多函數(shù)無(wú)法得到優(yōu)化,你可以在V8平臺(tái)使用--trace-opt file.js搭配d8實(shí)用程序。
如果你關(guān)心速度,那么盡最大努力確保單態(tài)函數(shù)(functions monomorphic),確保變量(包括屬性,數(shù)組和函數(shù)參數(shù))只適應(yīng)同樣的隱藏類包含的對(duì)象。
下面的代碼演示了,我們不可這么做:
function?add(x,?y)?{??return?x+y;?? }??add(1,?2);?? add('a','b');?? add(my_custom_object,?undefined);未初始化時(shí)不要加載和執(zhí)行刪除操作,因?yàn)樗鼈儾](méi)有輸出差異,這樣做反而會(huì)使程序變得更慢。不要編寫(xiě)大量函數(shù),函數(shù)越多越難優(yōu)化。
1.Objects使用技巧:
適應(yīng)構(gòu)造函數(shù)來(lái)創(chuàng)建對(duì)象。這將確保所創(chuàng)建的所有對(duì)象具備相同的隱藏類并有幫助避免更改這些類。
在程序或者復(fù)雜性上不要限制多種對(duì)象類型。(原因:長(zhǎng)原型鏈中傾向于傷害,只有極少數(shù)的對(duì)象屬性得到一個(gè)特殊的委托)對(duì)于活躍對(duì)象保持短原型鏈以及低字段計(jì)數(shù)。
2.對(duì)象克隆(Object Cloning)
對(duì)象克隆對(duì)于應(yīng)用開(kāi)發(fā)者來(lái)說(shuō)是一種常見(jiàn)的現(xiàn)象。雖然在V8中這是實(shí)現(xiàn)各種類型問(wèn)題的基準(zhǔn),但是當(dāng)你進(jìn)行復(fù)制時(shí),一定要當(dāng)心。當(dāng)復(fù)制較大的程序時(shí)通常很會(huì)慢,因此,盡量不要這么做。在JavaScript循環(huán)中此舉是非常糟糕的。這里有個(gè)最快的技巧方案,你不妨學(xué)習(xí)下:
function?clone(original)?{??this.foo?=?original.foo;??this.bar?=?original.bar;?? }?? var?copy?=?new?clone(original);3.模塊模式中的緩存功能
在模塊模式中使用緩存功能也許在性能方面會(huì)有所提升。請(qǐng)參閱下面的例子,通過(guò)jsPerf test測(cè)試。注,使用這種方法比依靠原型模式更佳。
推薦:這是測(cè)試原型與模塊模式性能代碼
?//?Prototypal?pattern??Klass1?=?function?()?{}??Klass1.prototype.foo?=?function?()?{??log('foo');??}??Klass1.prototype.bar?=?function?()?{??log('bar');??}??//?Module?pattern??Klass2?=?function?()?{??var?foo?=?function?()?{??log('foo');??},??bar?=?function?()?{??log('bar');??};??return?{??foo:?foo,??bar:?bar??}??}??//?Module?pattern?with?cached?functions??var?FooFunction?=?function?()?{??log('foo');??};??var?BarFunction?=?function?()?{??log('bar');??};??Klass3?=?function?()?{??return?{??foo:?FooFunction,??bar:?BarFunction??}??}??//?Iteration?tests??//?Prototypal??var?i?=?1000,??objs?=?[];??while?(i--)?{??var?o?=?new?Klass1()??objs.push(new?Klass1());??o.bar;??o.foo;??}??//?Module?pattern??var?i?=?1000,??objs?=?[];??while?(i--)?{??var?o?=?Klass2()??objs.push(Klass2());??o.bar;??o.foo;??}??//?Module?pattern?with?cached?functions??var?i?=?1000,??objs?=?[];??while?(i--)?{??var?o?=?Klass3()??objs.push(Klass3());??o.bar;??o.foo;??}?? //?See?the?test?for?full?details
4.數(shù)組使用技巧:
一般情況下,我們不要?jiǎng)h除數(shù)組元素。它是使數(shù)組過(guò)渡到較慢的內(nèi)部表現(xiàn)形式。當(dāng)密鑰集變得稀疏時(shí),V8最終將切換到字典模式,這是變慢的原因之一。
五、應(yīng)用優(yōu)化技巧:
在Web應(yīng)用領(lǐng)域里,速度就是一切。沒(méi)有用戶希望在啟動(dòng)電子表格時(shí)需要等上幾秒鐘,或者花上幾分鐘時(shí)間來(lái)整理信息。這也是為什么在性能方面,需要格外注意的一點(diǎn),有人甚至將編碼階段稱為至關(guān)重要的一部分。
理解和提升性能方面是非常有用的,但它也有一定的難度。這里推薦幾個(gè)步驟來(lái)幫你解決:
測(cè)試:在應(yīng)用程序中找到慢的節(jié)點(diǎn) (~45%)
理解:查找問(wèn)題所在(~45%)
修復(fù):(~10%)
當(dāng)然,還有許多工具或是技術(shù)方案幫助解決以上這些問(wèn)題:
1.基準(zhǔn)測(cè)試。在JavaScript上有許多方法可進(jìn)行基準(zhǔn)測(cè)試。
2.剖析。Chrome開(kāi)發(fā)工具能夠很好的支持JavaScript分析器。你可以使用這些性能進(jìn)行檢測(cè),哪些功能占用的時(shí)間比較長(zhǎng),然后對(duì)其進(jìn)行優(yōu)化。最重要的是,即使是很小的改變也能影響整體的表現(xiàn)。關(guān)于這款分析工具,這里有份詳細(xì)的介紹。
3.避免內(nèi)存泄露-3快照技術(shù)。谷歌開(kāi)發(fā)團(tuán)隊(duì)通常會(huì)使用Chrome開(kāi)發(fā)工具包括Gmail來(lái)幫助他們發(fā)現(xiàn)和修復(fù)內(nèi)存泄露;此外,3 snapshot也是不錯(cuò)的選擇。該技術(shù)允許在程序中記錄一些行為、強(qiáng)制垃圾回收、查詢,如果DOM節(jié)點(diǎn)無(wú)法返回預(yù)期的基線上,3 snapshot幫助分析確定是否存在內(nèi)存泄露。
4.單頁(yè)面程序上的內(nèi)存管理。當(dāng)你在編寫(xiě)單頁(yè)程序時(shí)(比如,AngularJS,Backbone,Ember)),內(nèi)存管理非常重要,他們從未得到刷新。這就意味著內(nèi)存泄露很明顯。在移動(dòng)單頁(yè)程序上存在著巨大的陷阱,因?yàn)閮?nèi)存有限,長(zhǎng)期運(yùn)行的程序比如email客戶端或者社交網(wǎng)絡(luò)應(yīng)用。因此,它肩負(fù)著巨大的責(zé)任。
Derick發(fā)表了這篇《memory pitfalls》教您如何使用Backbone.js以及如何進(jìn)行修復(fù)。Felix Geisendörfer的這篇在Node中調(diào)試內(nèi)存泄露也值得一讀。
5.最小化回流。回流是指在瀏覽器中用戶阻止此操作,所以它是有助于理解如何提高回流時(shí)間,你可以使用DocumentFragment一個(gè)輕量級(jí)的文檔對(duì)象來(lái)處理。
6.Javascript內(nèi)存泄露檢測(cè)器。由Marja Hölttä和Jochen Eisinger兩人開(kāi)發(fā)的這款工具,你不妨試試。
7.V8 flags調(diào)試優(yōu)化和內(nèi)存回收。Chrome支持通過(guò)flags和js-flags flag獲取更詳細(xì)的輸出:
例如:
"/Applications/Google?Chrome/Google?Chrome"?--js-flags="--trace-opt?--trace-deopt"Windows用戶運(yùn)行chrome.exe --js-flags="--trace-opt --trace-deopt"。
當(dāng)開(kāi)發(fā)應(yīng)用時(shí),可以使用下面的V8 flags:
trace-opt –日志名稱的優(yōu)化功能,顯示優(yōu)化跳過(guò)的代碼
trace-deopt –記錄運(yùn)行時(shí)將要“去優(yōu)化”的代碼。
trace-gc – 對(duì)每次垃圾回收時(shí)進(jìn)行跟蹤
結(jié)束語(yǔ):
正如上面提到的,在JavaScript引擎中有許多隱藏的陷阱,世界上沒(méi)有什么好的銀彈能夠幫助你提高性能,只有通過(guò)在測(cè)試環(huán)境中進(jìn)行優(yōu)化,實(shí)現(xiàn)最大的性能收益。因此,了解引擎如何輸出和優(yōu)化代碼可以幫助你調(diào)整應(yīng)用程序。
因此,測(cè)試它、理解它、修復(fù)它,如此往復(fù)!
英文出自:Coding.smashingmagazine
轉(zhuǎn)載于:https://my.oschina.net/maomi/blog/92028
總結(jié)
以上是生活随笔為你收集整理的【读书笔记】《编写高效的JavaScript程序》的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: shell 赋值
- 下一篇: JavaScript中使Promise模