萬盛學電腦網

 萬盛學電腦網 >> 腳本專題 >> javascript >> 怎樣為IE的javascript提速

怎樣為IE的javascript提速

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

01.(function( window, undefined ) { 
02. 

03.// Define a local copy of jQuery 
04.var jQuery = function( selector, context ) { 
05. 
// The jQuery object is actually just the init constructor 'enhanced' 
06. 
return new jQuery.fn.init( selector, context ); 
07. 
}, 
08. 

09. 
// Map over jQuery in case of overwrite 
10. 
_jQuery = window.jQuery, 
11. 

12. 
// Map over the $ in case of overwrite 
13. 
_$ = window.$, 
14. 

15. 
// Use the correct document accordingly with window argument (sandbox) 
16. 
document = window.document, 
17. 

18. 
//====================省================= 
19. 

20.// Expose jQuery to the global object 
21.window.jQuery = window.$ = jQuery; 
22. 

23.})(window); 
把window傳進閉包內,就省得它每次都往外找window了。

再看其他類庫

1.//Raphael 
2.window.Raphael = (function () { 
3. 
var separator = /[, ]+/, 
4. 
elements = /^(circle|rect|path|ellipse|text|image)$/, 
5. 
doc = document, 
6. 
win = window, 
7.//************略************** 1.//dojo 
2.d.global = this; 1.//Ext 
2.DOC = document, 01.//YUI 
02.//************略************ 
03. 
} else if (i == 'win') { 
04. 
c[i] = o[i].contentWindow || o[i]; 
05. 
c.doc = c[i].document; 
06.//************略************ 
07.Y.config = { 
08. 

09. 
win: window || {}, 
10. 
doc: document, 
但是如果你沒有引入類庫,如果讓IE的javascript跑得更快些呢?用一個變量把它儲存起來?在日本博客看到一種很厲害的劫持技術,偷龍轉鳳把全局變量document變成一個局部變量。

view sourceprint?1./*@cc_on _d=document;eval('var document=_d')@*/ 
<!doctype html>
<html dir="ltr" lang="zh-CN">
<head>
<meta charset="utf-8"/>
<title>javascript提速技術 by 司徒正美</title>

<script type="text/javascript">

var date = new Date;
for (var i = 0; i < 100000; i++) document;

alert(new Date - date); 

</script>

</head>
<body>
</body>
</html>

運行代碼

運用提速技術後:


<!doctype html>
<html dir="ltr" lang="zh-CN">
<head>
<meta charset="utf-8"/>
<title>javascript提速技術 by 司徒正美</title>

<script type="text/javascript">
/*@cc_on _d=document;eval('var document=_d')@*/

var date = new Date;
for (var i = 0; i < 100000; i++) document;

alert(new Date - date); 

</script>

</head>
<body>
!!!!!!!!
</body>
</html>

運行代碼

經測試,用了提速技術後,IE的性能比較

IE6 
document document.getElementById document.title 
沒有使用提速技術 485 1110 1219 
使用提速技術後 109 609 656 
IE8 
document document.getElementById document.title 
沒有使用提速技術 468 797 843 
使用提速技術後 78 328 407

我們看一下實現原理:

view sourceprint?1.document; 
2.doc; //很明顯,調用這個比直接document快,document還要鑽進window內部找一番 
如何劫持它呢?

view sourceprint?1.var doc = document; 
2.var document = doc; 
這樣明顯不行因為在預編譯階段,var變量會提前,上面代碼相當於

view sourceprint?1.var doc 
2.var document //這裡被劫持了 
3.doc = document //注意,document已經變成undefined 
4.document = doc //相當於window.undefined = undefined 
沒有辦法,只好在執行期才定義這個document變量,javascript的動態解析技術派上用場了,eval就是其代表之一。

view sourceprint?1.var doc = document; 
2.eval('var document = doc'); 
為了讓IE專用,用了IE特有的條件編譯。

view sourceprint?1./*@cc_on 
2.var doc = document; 
3.eval('var document = doc'); 
4.@*/
嘛,window的東西其實蠻多,我們一一把它們變成本地變量又如何?

view sourceprint?01./*@cc_on 
02.eval((function(props) { 
03. 
var code = []; 
04. 
for (var i = 0 l = props.length;i<l;i++){ 
05. 
var prop = props[i]; 
06. 
window['_'+prop]=window[prop]; 
07. 
code.push(prop+'=_'+prop) 
08. 

09. 
return 'var '+code.join(','); 
10.})('document event body location title self top parent alert setInterval clearInterval setTimeout clearTimeout'.split(' '))); 
11.@*/
我們可以再擴展一下,讓其更多全局變量或全局方法局部化。不過經驗測,FF使用它會報錯,chrome則慢了,其他浏覽器不明顯。

view sourceprint?01.if( !+"v1" ){ 
02. 
var code = [],ri = 0,prop,str = "var "
03. 
for(var a in window) 
04. 
code[ri++] = a; 
05. 
for (var i = 0 ,n = code.length;i<n;i++){ 
06. 
var prop = code[i] 
07. 
window['_'+prop] = window[prop]; 
08. 
str += prop+'=_'+prop+","
09. 

10. 
str = str.slice(0,-1); 
11. 
eval(str) 
12.} 
<!doctype html>
<html dir="ltr" lang="zh-CN">
<head>
<meta charset="utf-8"/>
<title>javascript提速技術 by 司徒正美</title>

<script type="text/javascript">
var __chrome = navigator.userAgent.indexOf("Chrome") !== -1;
var __firefox = !!window.Components

if( !__chrome & !__firefox ){

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)
}
var date = new Date;
for (var i = 0; i < 100000; i++)
document;

alert(new Date - date); 

</script>

</head>
<body>
!!!!!!
</body>
</html>

copyright © 萬盛學電腦網 all rights reserved