為IE的javascript提速

來源:互聯網
上載者:User

我們知道,javascript在執行期時是由內到外執行指令碼的,那麼離我們的指令碼最遠的全域對象,很可能要跨越幾層範圍才能訪問到它。不過在IE中,從最內層到最外層要花的時間比其他多出很多。加之,javascript是一種膠水語言,它必須要調用DOM對能完成我們大多數選擇。最著名的就是選擇元素(document.getElementById,document.getElementsByTagName,docuemnt.evaluate,document.querySelector),建立元素(document.createElement),此外還有document.body,document.defaultView.getComputedStyle等等,頻繁地調用document對象,但是document是位於window對象下,因此這路程就更遠了。就了提速,我們必須把它們儲存在一個本地變數,那麼每次就省得它長途跋涉了。這種技術的運用明顯體現在jQuery的源碼中:

(function( window, undefined ) {// Define a local copy of jQueryvar jQuery = function( selector, context ) {// The jQuery object is actually just the init constructor 'enhanced'return new jQuery.fn.init( selector, context );},// Map over jQuery in case of overwrite_jQuery = window.jQuery,// Map over the $ in case of overwrite_$ = window.$,// Use the correct document accordingly with window argument (sandbox)document = window.document,        //====================省=================       }// Expose jQuery to the global objectwindow.jQuery = window.$ = jQuery;})(window);                

把window傳進閉包內,就省得它每次都往外找window了。

再看其他類庫

//Raphael window.Raphael = (function () {    var separator = /[, ]+/,        elements = /^(circle|rect|path|ellipse|text|image)$/,        doc = document,        win = window,//************略**************                
//dojod.global = this;                
//ExtDOC = document,                
//YUI//************略************            } else if (i == 'win') {                c[i] = o[i].contentWindow || o[i];                c.doc = c[i].document;//************略************Y.config = {            win: window || {},            doc: document,                

但是如果你沒有引入類庫,如果讓IE的javascript跑得更快些呢?用一個變數把它儲存起來?在日本部落格看到一種很厲害的劫持技術,偷龍轉鳳把全域變數document變成一個局部變數。

/*@cc_on _d=document;eval('var document=_d')@*/                

<br /><!doctype html><br /><html dir="ltr" lang="zh-CN"><br /> <head><br /> <meta charset="utf-8"/><br /> <title>javascript提速技術 by 司徒正美</title></p><p> <script type="text/javascript"></p><p>var date = new Date;<br />for (var i = 0; i </p><p><button type="button" class="runcode" title="runcode1">運行代碼</button></p><p>運用提速技術後:</p><p> <textarea id="runcode2" style="width:75%" rows="10"><br /><!doctype html><br /><html dir="ltr" lang="zh-CN"><br /> <head><br /> <meta charset="utf-8"/><br /> <title>javascript提速技術 by 司徒正美</title></p><p> <script type="text/javascript"><br /> /*@cc_on _d=document;eval('var document=_d')@*/</p><p>var date = new Date;<br />for (var i = 0; i </p><p><button type="button" class="runcode" title="runcode2">運行代碼</button></p><p>經測試,用了提速技術後,IE的效能比較</p><table class="filament_table" cellspacing="0" width="700" rules="cols"><col class="yellow" width="24%"><col class="grey" width="15%"><col class="yellow"><col class="grey" width="26%"><thead><tr><th colspan="4">IE6</th></tr><tr><th></th><th>document</th><th>document.getElementById</th><th>document.title</th></tr></thead><tbody><tr><td>沒有使用提速技術</td><td>485</td><td>1110 </td><td>1219</td></tr><tr><td>使用提速技術後</td><td>109</td><td>609 </td><td>656</td></tr></tbody></table><table class="filament_table" cellspacing="0" width="700" rules="cols"><col class="yellow" width="24%"><col class="grey" width="15%"><col class="yellow"><col class="grey" width="26%"><thead><tr><th colspan="4">IE8</th></tr><tr><th></th><th>document</th><th>document.getElementById</th><th>document.title</th></tr></thead><tbody><tr><td>沒有使用提速技術</td><td>468 </td><td>797 </td><td>843</td></tr><tr><td>使用提速技術後</td><td>78 </td><td>328 </td><td>407</td></tr></tbody></table><p>我們看一下實現原理:</p><pre class="brush:javascript;gutter:false;toolbar:toolbar:false">document; doc; //很明顯,調用這個比直接document快,document還要鑽進window內部找一番 </pre><p>如何劫持它呢?</p><pre class="brush:javascript;gutter:false;toolbar:toolbar:false">var doc = document;var document = doc; </pre><p>這樣明顯不行因為在先行編譯階段,var變數會提前,上面代碼相當於</p><pre class="brush:javascript;gutter:false;toolbar:toolbar:false">var docvar document //這裡被劫持了doc = document //注意,document已經變成undefineddocument = doc //相當於window.undefined = undefined </pre><p>沒有辦法,只好在執行期才定義這個document變數,javascript的動態解析技術派上用場了,eval就是其代表之一。</p><pre class="brush:javascript;gutter:false;toolbar:toolbar:false">var doc = document;eval('var document = doc'); </pre><p>為了讓IE專用,用了IE特有的條件編譯。</p><pre class="brush:javascript;gutter:false;toolbar:toolbar:false">/*@cc_on var doc = document;eval('var document = doc');@*/ </pre><p>嘛,window的東西其實蠻多,我們一一把它們變成本地變數又如何?</p><pre class="brush:javascript;gutter:false;toolbar:toolbar:false">/*@cc_oneval((function(props) { var code = []; for (var i = 0 l = props.length;i<l;i++){ var prop = props[i]; window['_'+prop]=window[prop]; code.push(prop+'=_'+prop) } return 'var '+code.join(',');})('document event body location title self top parent alert setInterval clearInterval setTimeout clearTimeout'.split(' ')));@*/ </pre><p>我們可以再擴充一下,讓其更多全域變數或全域方法局部化。不過經驗測,FF使用它會報錯,chrome則慢了,其他瀏覽器不明顯。</p><pre class="brush:javascript;gutter:false;toolbar:toolbar:false"> if( !+"\v1" ){ var code = [],ri = 0,prop,str = "var " for(var a in window) code[ri++] = a; for (var i = 0 ,n = code.length;i<n;i++){ var prop = code[i] window['_'+prop] = window[prop]; str += prop+'=_'+prop+"," } str = str.slice(0,-1); eval(str) } </pre><p> <textarea id="runcode3" style="width:75%" rows="10"><br /><!doctype html><br /><html dir="ltr" lang="zh-CN"><br /> <head><br /> <meta charset="utf-8"/><br /> <title>javascript提速技術 by 司徒正美</title></p><p> <script type="text/javascript"><br /> var __chrome = navigator.userAgent.indexOf("Chrome") !== -1;<br /> var __firefox = !!window.Components</p><p> if( !__chrome & !__firefox ){</p><p> var code = [],ri = 0,prop,str = "var "<br /> for(var a in window)<br /> code[ri++] = a;<br /> for (var i = 0 ,n = code.length;i<n;i++){<br /> var prop = code[i]<br /> window['_'+prop] = window[prop];<br /> str += prop+'=_'+prop+","<br /> }<br /> str = str.slice(0,-1);<br /> eval(str)<br /> }<br />var date = new Date;<br />for (var i = 0; i </p><p><button type="button" class="runcode" title="runcode3">運行代碼</button></p><p>

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.