4、减少作用域链上的查找次数
我们知道,js代码在执行的时候,如果需要访问一个变量或者一个函数的时候,它需要遍历当前执行环境的作用域链,而遍历是从这个作用域链的前端一级一级的向后遍历,直到全局执行环境,所以这里往往会出现一个情况,那就是如果我们需要经常访问全局环境的变量对象的时候,我们每次都必须在当前作用域链上一级一级的遍历,这显然是比较耗时的,我们看下面的例子:
< div id = "demo" ></ div > < input id = "but1" type = "button" onclick = "func1()" value = "效率低" /> < input id = "but2" type = "button" onclick = "func2()" value = "效率高" /> |
function func1(){
var start = new Date().getTime();
for ( var i = 0; i < 10000; i++){
var but1 = document.getElementById( "but1" );
var but2 = document.getElementById( "but2" );
var inputs = document.getElementsByTagName( "input" );
var divs = document.getElementsByTagName( "div" );
var but1 = document.getElementById( "but1" );
var but2 = document.getElementById( "but2" );
var inputs = document.getElementsByTagName( "input" );
var divs = document.getElementsByTagName( "div" );
var but1 = document.getElementById( "but1" );
var but2 = document.getElementById( "but2" );
var inputs = document.getElementsByTagName( "input" );
var divs = document.getElementsByTagName( "div" );
var but1 = document.getElementById( "but1" );
var but2 = document.getElementById( "but2" );
var inputs = document.getElementsByTagName( "input" );
var divs = document.getElementsByTagName( "div" );
var but1 = document.getElementById( "but1" );
var but2 = document.getElementById( "but2" );
var inputs = document.getElementsByTagName( "input" );
var divs = document.getElementsByTagName( "div" );
var but1 = document.getElementById( "but1" );
var but2 = document.getElementById( "but2" );
var inputs = document.getElementsByTagName( "input" );
var divs = document.getElementsByTagName( "div" );
}
var end = new Date().getTime();
alert( "用时 " + (end - start) + " 毫秒" ); } function func2(){
var start = new Date().getTime();
var doc = document;
for ( var i = 0; i < 10000; i++){
var but1 = doc.getElementById( "but1" );
var but2 = doc.getElementById( "but2" );
var inputs = doc.getElementsByTagName( "input" );
var divs = doc.getElementsByTagName( "div" );
var but1 = doc.getElementById( "but1" );
var but2 = doc.getElementById( "but2" );
var inputs = doc.getElementsByTagName( "input" );
var divs = doc.getElementsByTagName( "div" );
var but1 = doc.getElementById( "but1" );
var but2 = doc.getElementById( "but2" );
var inputs = doc.getElementsByTagName( "input" );
var divs = doc.getElementsByTagName( "div" );
var but1 = doc.getElementById( "but1" );
var but2 = doc.getElementById( "but2" );
var inputs = doc.getElementsByTagName( "input" );
var divs = doc.getElementsByTagName( "div" );
var but1 = doc.getElementById( "but1" );
var but2 = doc.getElementById( "but2" );
var inputs = doc.getElementsByTagName( "input" );
var divs = doc.getElementsByTagName( "div" );
var but1 = doc.getElementById( "but1" );
var but2 = doc.getElementById( "but2" );
var inputs = doc.getElementsByTagName( "input" );
var divs = doc.getElementsByTagName( "div" );
}
var end = new Date().getTime();
alert( "用时 " + (end - start) + " 毫秒" ); } |
上面代码中,第二种情况是先把全局对象的变量放到函数里面先保存下来,然后直接访问这个变量,而第一种情况是每次都遍历作用域链,直到全局环境,我们看到第二种情况实际上只遍历了一次,而第一种情况却是每次都遍历了,所以我们看看其执行结果:
IE6.0 | ||||||
函数 | 第1次 | 第2次 | 第3次 | 第4次 | 第5次 | 平均 |
func1 | 1627ms | 1627ms | 1642ms | 1627ms | 1626ms | 1629.8ms |
func2 | 985ms | 1002ms | 1001ms | 985ms | 985ms | 991.6ms |
Firefox4.0 | ||||||
函数 | 第1次 | 第2次 | 第3次 | 第4次 | 第5次 | 平均 |
func1 | 72ms | 71ms | 72ms | 72ms | 82ms | 73.8ms |
func2 | 72ms | 71ms | 73ms | 83ms | 70ms | 73.8ms |
Chrome6.0 | ||||||
函数 | 第1次 | 第2次 | 第3次 | 第4次 | 第5次 | 平均 |
func1 | 62ms | 71ms | 63ms | 78ms | 78ms | 70.4ms |
func2 | 78ms | 62ms | 62ms | 71ms | 62ms | 67ms |
从上表中可以看出,其在IE6下差别还是非常明显的,而且这种差别在多级作用域链和多个全局变量的情况下还会表现的非常明显。