Ale*_*olo 4 javascript arrays optimization loops
我们假设我们应该得到一些数据......
var data = [];
//some code omitted that might fill in the data (though might not)
Run Code Online (Sandbox Code Playgroud)
然后我们需要对数据做些什么.我的问题是如何更有效地做到这一点.像这样?:
if (data.length) {
for (var i = 0; i < data.length; i++) {
//iterate over the data and do something to it
}
}
Run Code Online (Sandbox Code Playgroud)
或者就是这样?:
for (var i = 0; i < data.length; i++) {
//iterate over the data and do something to it
}
Run Code Online (Sandbox Code Playgroud)
重点是在迭代之前是否检查长度?
我不认为值得检查是否for基于lengthof 来执行循环,data因为如果for循环仅执行几次,它可能在性能方面没有太大差别.
但通常,首先获得长度更快,而不是i<data.length每次都需要访问变量.至于哪种方式最有效地循环数据,不同的浏览器针对不同类型的循环进行了优化.然而,它只是IE 非常慢(在下面的测试中比其他浏览器慢几个数量级)所以我认为优化其他浏览器可能不值得.
以下是基准测试的结果(最快用+表示,最慢用 - 表示):
FF Chrome Safari Opera IE6 IE7 IE8
Method 1 +0.163+ 0.221 0.246 0.269 -11.608- -12.214- -7.657-
Method 2 0.175 +0.133+ 0.176 +0.147+ 8.474 8.752 3.267
Method 3 0.206 0.235 0.276 0.245 8.002 8.539 3.651
Method 4 0.198 0.372 0.447 0.390 +6.562+ +7.020+ 2.920
Method 5 0.206 0.372 0.445 -0.400- 6.626 7.096 +2.905+
Method 6 0.176 0.167 +0.175+ 0.223 7.029 8.085 3.167
Method 7 -0.263- -0.567- -0.449- 0.413 6.925 7.431 3.242
方法1:使用"标准" for循环:
for (var i=0; i<data.length; i++) {
var x = data[i]
}
Run Code Online (Sandbox Code Playgroud)
方法2:使用"标准" for循环,分配length,使其不必每次访问:
for (var i=0, len=data.length; i<len; i++) {
var x = data[i]
}
Run Code Online (Sandbox Code Playgroud)
方法3:这类似于jQuery使用的方法$.each().请注意分配,len以便它不必length每次都获取.
for (var x=data[0], len=data.length, i=0; i<len; x=data[++i]) {}
Run Code Online (Sandbox Code Playgroud)
方法4:使用while循环,前进.警告:需要每个项目在数组中,以评估true,即不false,0,null,undefined,''等!
var x, i=0
while (x = data[i++]) {}
Run Code Online (Sandbox Code Playgroud)
方法5:与方法4相同,仅for用于执行相同操作:
for (var x,i=0; x=data[i++];) {}
Run Code Online (Sandbox Code Playgroud)
方法6:使用while以下方法向后循环循环:
var i = data.length
while (i--) {
var x = data[i]
}
Run Code Online (Sandbox Code Playgroud)
方法7:使用方法4 /方法5,但不需要评估项目true,替换x = data[i++]:
var x, i=0, len=data.length
while ((x=data[i++]) || i<len) {}
Run Code Online (Sandbox Code Playgroud)
这首先检查是否data[i++]计算true然后检查它是否是最后一项,以便它在IE中具有类似的性能,null并且false数组中的等等问题更少.请注意,在这种情况下使用whilevs 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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
318 次 |
| 最近记录: |