我們知道,javascript在執(zhí)行期時(shí)是由內(nèi)到外執(zhí)行腳本的,那么離我們的腳本最遠(yuǎn)的全局對(duì)象,很可能要跨越幾層作用域才能訪問(wèn)到它。不過(guò)在IE中,從最內(nèi)層到最外層要花的時(shí)間比其他多出很多。加之,javascript是一種膠水語(yǔ)言,它必須要調(diào)用DOM對(duì)能完成我們大多數(shù)選擇。最著名的就是選擇元素(document.getElementById,document.getElementsByTagName,docuemnt.evaluate,document.querySelector),創(chuàng)建元素(document.createElement),此外還有document.body,document.defaultView.getComputedStyle等等,頻繁地調(diào)用document對(duì)象,但是document是位于window對(duì)象下,因此這路程就更遠(yuǎn)了。就了提速,我們必須把它們保存在一個(gè)本地變量,那么每次就省得它長(zhǎng)途跋涉了。這種技術(shù)的運(yùn)用明顯體現(xiàn)在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傳進(jìn)閉包內(nèi),就省得它每次都往外找window了。
再看其他類庫(kù)
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,
但是如果你沒(méi)有引入類庫(kù),如果讓IE的javascript跑得更快些呢?用一個(gè)變量把它儲(chǔ)存起來(lái)?在日本博客看到一種很厲害的劫持技術(shù),偷龍轉(zhuǎn)鳳把全局變量document變成一個(gè)局部變量。
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提速技術(shù) 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>
運(yùn)行代碼
運(yùn)用提速技術(shù)后:
<!doctype html>
<html dir="ltr" lang="zh-CN">
<head>
<meta charset="utf-8"/>
<title>javascript提速技術(shù) 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>
運(yùn)行代碼
經(jīng)測(cè)試,用了提速技術(shù)后,IE的性能比較
IE6
document document.getElementById document.title
沒(méi)有使用提速技術(shù) 485 1110 1219
使用提速技術(shù)后 109 609 656
IE8
document document.getElementById document.title
沒(méi)有使用提速技術(shù) 468 797 843
使用提速技術(shù)后 78 328 407
我們看一下實(shí)現(xiàn)原理:
view sourceprint?1.document;
2.doc; //很明顯,調(diào)用這個(gè)比直接document快,document還要鉆進(jìn)window內(nèi)部找一番
如何劫持它呢?
view sourceprint?1.var doc = document;
2.var document = doc;
這樣明顯不行因?yàn)樵陬A(yù)編譯階段,var變量會(huì)提前,上面代碼相當(dāng)于
view sourceprint?1.var doc
2.var document //這里被劫持了
3.doc = document //注意,document已經(jīng)變成undefined
4.document = doc //相當(dāng)于window.undefined = undefined
沒(méi)有辦法,只好在執(zhí)行期才定義這個(gè)document變量,javascript的動(dòng)態(tài)解析技術(shù)派上用場(chǎng)了,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的東西其實(shí)蠻多,我們一一把它們變成本地變量又如何?
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.@*/
我們可以再擴(kuò)展一下,讓其更多全局變量或全局方法局部化。不過(guò)經(jīng)驗(yàn)測(cè),F(xiàn)F使用它會(huì)報(bào)錯(cuò),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提速技術(shù) 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>