我认为基于data 的length 执行for 循环不值得检查,因为如果只执行for 循环,它可能不会对性能产生太大影响几次。
但通常首先获取长度比将其设置为 i<data.length 更快,因为它每次都需要访问变量。至于哪种方式循环数据效率最高,不同的浏览器针对不同的循环进行了优化。但是,只有 IE严重 很慢(在以下测试中比其他浏览器慢几个数量级),所以我认为针对其他浏览器进行优化可能不值得。
以下是以下基准测试的结果(最快用 + 表示,最慢用 - 表示):
FF Chrome Safari Opera IE6 IE7 IE8
方法1 +0.163+ 0.221 0.246 0.269 -11.608- -12.214- -7.657-
方法2 0.175 +0.133+ 0.176 +0.147+ 8.474 8.752 3.267
方法3 0.206 0.235 0.276 0.245 8.002 8.539 3.651
方法4 0.198 0.372 0.447 0.390 +6.562+ +7.020+ 2.920
方法5 0.206 0.372 0.445 -0.400- 6.626 7.096 +2.905+
方法6 0.176 0.167 +0.175+ 0.223 7.029 8.085 3.167
方法7 -0.263- -0.567- -0.449- 0.413 6.925 7.431 3.242
方法一:使用“标准”for循环:
for (var i=0; i<data.length; i++) {
var x = data[i]
}
方法2:使用“标准”for循环,分配length,这样就不必每次都访问了:
for (var i=0, len=data.length; i<len; i++) {
var x = data[i]
}
方法 3: 这类似于 jQuery 在$.each() 中使用的方法。注意分配给len,这样它就不必每次都得到length。
for (var x=data[0], len=data.length, i=0; i<len; x=data[++i]) {}
方法4:使用while循环,往前走。 警告: 需要数组中的每个项目评估为true,即不是false、0、null、undefined、'' 等!
var x, i=0
while (x = data[i++]) {}
方法五:同方法四,只是用for做同样的事情:
for (var x,i=0; x=data[i++];) {}
方法6:使用while向后循环循环:
var i = data.length
while (i--) {
var x = data[i]
}
方法 7: 使用方法 4/方法 5,但不需要评估项目到 true,替换 x = data[i++]:
var x, i=0, len=data.length
while ((x=data[i++]) || i<len) {}
这首先检查data[i++] 的计算结果是否为true,然后检查它是否是最后一项,以便它可以在IE 中具有类似的性能,而数组中的null 和false 等问题更少。请注意,在这种情况下使用 while 与 for 时没有明显的区别,但我更喜欢 while,因为我认为它更清晰。
我通常不喜欢优化,除非有特定的长时间运行的任务,因为它通常会以可读性为代价 - 请仅在您有大量数据需要的特定情况下进行加载等:-)
编辑:因为方法 4/5 在 IE 上非常快,所以添加了一个副作用更少的版本。
编辑 2: 重做所有测试,这次没有任何浏览器扩展,而且时间更长。为了完整起见,这里是代码(抱歉让这篇文章这么长:)
function Tmr() {
this.tStart = new Date()
}
Tmr.prototype = {
Time: function() {
var tDate = new Date()
var tDiff = tDate.getTime() - this.tStart.getTime()
var tDiff = tDiff / 1000.0 // Convert to seconds
return tDiff
}
}
function normalfor(data) {
for (var i=0; i<data.length; i++) {
var x = data[i]
}
}
function fasterfor(data) {
for (var i=0, len=data.length; i<len; i++) {
var x = data[i]
}
}
function jqueryfor(data) {
for (var x=data[0], len=data.length, i=0; i<len; x=data[++i]) {
}
}
function whileloop(data) {
var x, i=0
while (x = data[i++]) {
}
}
function fixedwhileloop(data) {
var x, i=0, len=data.length
while ((x=data[i++]) || i<len) {
}
}
function forwhileloop(data) {
for (var x,i=0; x=data[i++];) {
}
}
function fixedforwhileloop(data) {
for (var x,i=0,len=data.length; (x=data[i++])||i<len; ) {
}
}
function whilebackwards(data) {
var i = data.length
while (i--) {
var x = data[i]
}
}
var undefined
var NUMTIMES = 1000000
var data = '$blah blah blah blah blah|'.split('')
function test() {}
function getfntime(fn) {
// Get the rough time required when executing one of the above functions
// to make sure the `for` loop and function call overhead in `run` doesn't
// impact the benchmarks as much
var t = new Tmr()
for (var xx=0; xx<NUMTIMES; xx++) {
fn()
}
return t.Time()
}
var fntime = getfntime(test)
function run(fn, i){
var t = new Tmr()
for (var xx=0; xx<NUMTIMES; xx++) {
fn(data)
}
alert(i+' '+(t.Time()-fntime))
}
setTimeout('run(normalfor, "1:normalfor")', 0)
setTimeout('run(fasterfor, "2:fasterfor")', 0)
setTimeout('run(jqueryfor, "3:jqueryfor")', 0)
setTimeout('run(whileloop, "4:whileloop")', 0)
setTimeout('run(forwhileloop, "5:forwhileloop")', 0)
setTimeout('run(whilebackwards, "6:whilebackwards")', 0)
setTimeout('run(fixedwhileloop, "7:fixedwhileloop")', 0)
//setTimeout('run(fixedforwhileloop, "8:fixedforwhileloop")', 0)