为了测试javascript函数在执行的过程中,对局部变量的赋值开销以及缓存全局变量或者dom属性(方法)的开销,特别写了如下三个简单的测试函数:
函数一:正常使用,循环10000次调用document.getElementsByTagName
function test1(){
for(var i=0;i<10000;i++){
var el = document.getElementsByTagName('div');
}
};
函数二:缓存document对象,作为减少函数调用中搜索作用域链的开销,但增加了一个局部变量的赋值开销
_d = document,循环的次数仍然是10000次。
function test2(){
var el,_d = document;
for(var i=0;i<10000;i++){
el = _d.getElementsByTagName('div');
}
};
函数三:缓存dom的方法进行调用在IE6下非常耗时,是三个函数中最慢的,并且在FF&chrome马上挂死掉.
function test3(){
var el,_d = document.getElementsByTagName;
for(var i=0;i<10000;i++){
el = _d('div');
}
};
下面是在IE6和FireFox3.0.14想进行测试的时间开销:
IE6下:
test1() test2() test3()
第一次: 406ms 219ms 1250ms
第二次: 516ms 250ms 1266ms
第三次: 469ms 250ms 1266ms
第四次: 453ms 250ms 1250ms
第五次: 422ms 203ms 1312ms
第六次: 437ms 219ms 1235ms
第七次: 422ms 219ms 1250ms
第八次: 454ms 265ms 1250ms
第九次: 437ms 219ms 1281ms
第十次: 406ms 219ms 1250ms
FireFox下:
test1() test2() test3()
第一次: 229ms 156ms -
第二次: 226ms 184ms -
第三次: 248ms 181ms -
第四次: 184ms 159ms -
第五次: 215ms 180ms -
第六次: 210ms 177ms -
第七次: 196ms 169ms -
第八次: 202ms 175ms -
第九次: 192ms 175ms -
第十次: 202ms 175ms -
从上面的测试数据可以得出比较重要的结论:
1,FireFox在dom的操作效率上确实比IE要快了许多,这点毫无疑问的。
2,在一个函数的执行过程中,如果对dom存在多次的引用,可以通过缓存成函数的局部变量来缩短搜索scopechain的开销,加快函数调用的执行效率,但这里也要考虑局部变量赋值的开销情况。
3,在IE6下发现缓存document.getElementById或者document.getElementsByTagName,然后进行调用的执行效率更差,并且该缓存的方法在Firefox和chrome下无法执行,出现类型错误等,具体原因主要是Firefox等跟IE对host object的实现不一样导致的,而ECMA对host object没有明确的规定,经过测试发现:
IE下:
var fn = document.getElementsByTagName;
fn('divid'); //可以正常进行调用
alert(typeof fn); //输出object类型,而不是function类型
fn.call(document, 'divid');//无法调用,提示没有call方法
fn.apply(document, ['divid']);//无法调用,提示没有apply方法
Firefox下:
var fn = document.getElementsByTagName;
fn('divid'); //无法进行调用,但下面的方法可以:
//主要原因是把document的方法作为一个引用保持到一个全局变量导致this指针变成了global对象,因此进行调用的时候
//提示非法类型错误
fn.call(document, 'divid');
alert(typeof fn); //输出function类型,而不是object类型
fn.call(document, 'divid'); //可以正常使用
fn.apply(document, ['divid']); //可以正常使用
4:对函数进行引用保存后再调用的时候,要主要可能导致内部的this指针“漂移”的问题,特别是之前是一个对象的方法,而后保存成一个全局的变量,而后者进行调用的时候,实际上this指针跟之前的已经不一样了。
5,对dom中的方法,IE和Firefox等存在较多的差异,Firefox相对更加标准,IE对dom的方法和属性的类型均是object,对应的方法也可能不存在对应的call和apply方法。(注意:ECMA-262规范对host object的类型等没有明确的规定)
[img]
[/img]
函数一:正常使用,循环10000次调用document.getElementsByTagName
function test1(){
for(var i=0;i<10000;i++){
var el = document.getElementsByTagName('div');
}
};
函数二:缓存document对象,作为减少函数调用中搜索作用域链的开销,但增加了一个局部变量的赋值开销
_d = document,循环的次数仍然是10000次。
function test2(){
var el,_d = document;
for(var i=0;i<10000;i++){
el = _d.getElementsByTagName('div');
}
};
函数三:缓存dom的方法进行调用在IE6下非常耗时,是三个函数中最慢的,并且在FF&chrome马上挂死掉.
function test3(){
var el,_d = document.getElementsByTagName;
for(var i=0;i<10000;i++){
el = _d('div');
}
};
下面是在IE6和FireFox3.0.14想进行测试的时间开销:
IE6下:
test1() test2() test3()
第一次: 406ms 219ms 1250ms
第二次: 516ms 250ms 1266ms
第三次: 469ms 250ms 1266ms
第四次: 453ms 250ms 1250ms
第五次: 422ms 203ms 1312ms
第六次: 437ms 219ms 1235ms
第七次: 422ms 219ms 1250ms
第八次: 454ms 265ms 1250ms
第九次: 437ms 219ms 1281ms
第十次: 406ms 219ms 1250ms
FireFox下:
test1() test2() test3()
第一次: 229ms 156ms -
第二次: 226ms 184ms -
第三次: 248ms 181ms -
第四次: 184ms 159ms -
第五次: 215ms 180ms -
第六次: 210ms 177ms -
第七次: 196ms 169ms -
第八次: 202ms 175ms -
第九次: 192ms 175ms -
第十次: 202ms 175ms -
从上面的测试数据可以得出比较重要的结论:
1,FireFox在dom的操作效率上确实比IE要快了许多,这点毫无疑问的。
2,在一个函数的执行过程中,如果对dom存在多次的引用,可以通过缓存成函数的局部变量来缩短搜索scopechain的开销,加快函数调用的执行效率,但这里也要考虑局部变量赋值的开销情况。
3,在IE6下发现缓存document.getElementById或者document.getElementsByTagName,然后进行调用的执行效率更差,并且该缓存的方法在Firefox和chrome下无法执行,出现类型错误等,具体原因主要是Firefox等跟IE对host object的实现不一样导致的,而ECMA对host object没有明确的规定,经过测试发现:
IE下:
var fn = document.getElementsByTagName;
fn('divid'); //可以正常进行调用
alert(typeof fn); //输出object类型,而不是function类型
fn.call(document, 'divid');//无法调用,提示没有call方法
fn.apply(document, ['divid']);//无法调用,提示没有apply方法
Firefox下:
var fn = document.getElementsByTagName;
fn('divid'); //无法进行调用,但下面的方法可以:
//主要原因是把document的方法作为一个引用保持到一个全局变量导致this指针变成了global对象,因此进行调用的时候
//提示非法类型错误
fn.call(document, 'divid');
alert(typeof fn); //输出function类型,而不是object类型
fn.call(document, 'divid'); //可以正常使用
fn.apply(document, ['divid']); //可以正常使用
4:对函数进行引用保存后再调用的时候,要主要可能导致内部的this指针“漂移”的问题,特别是之前是一个对象的方法,而后保存成一个全局的变量,而后者进行调用的时候,实际上this指针跟之前的已经不一样了。
5,对dom中的方法,IE和Firefox等存在较多的差异,Firefox相对更加标准,IE对dom的方法和属性的类型均是object,对应的方法也可能不存在对应的call和apply方法。(注意:ECMA-262规范对host object的类型等没有明确的规定)
[img]
[/img]