【JS】Array 循环5万数据并删除1万数据,对比Delete与Splice 的运行效果。
已经很晚了,但是,还是把中午实验的东西码上来吧,不然我就可能要忘记了,快点写完,好休息,趁这几天还有激情研究代码,多写点,充实充实自己。
JS 中有 Object 的 delete
语法 Array 也同样适用 而 Array 还有更多的对自己操作的方法,什么splice()
shift()
pop()
...
嗯,都是可以进行修改数组长度的方法,但其中的效率可真的是没有对比就看不到伤害(cha ju),今天(看时间也是今晚,哦不!明天。。。)这篇文章就为了对一些 需要性能的场景 做一个简单的分析,可谓及其粗暴(jian dan)。还是直接放代码,然后截图最明白了。。。
实例代码
var testArray = [],testArray2=[],testArray3=[];
for(var i=0;i<50000;i++){
//模拟复杂的数据 简单的数据就不要这么搞了,直接用复制的方式比下面这些块的多
testArray.push({x:1024.1024,y:1024.1024,name:"1024",_this:this,arr:[1024.1024,1024.1024,1024.1024,1024.1024]});
//尽量让两个循环公平些
testArray2.push({x:1024.1024,y:1024.1024,name:"1024",_this:this,arr:[1024.1024,1024.1024,1024.1024,1024.1024]});
//就让你看看复制有多快 就是用来秒杀上面的
testArray3.push({x:1024.1024,y:1024.1024,name:"1024",_this:this,arr:[1024.1024,1024.1024,1024.1024,1024.1024]});
}
// 第一个循环开始
var start = Date.now();
var i=0,maxlen =testArray.length,last =maxlen-1 ,delspan=5;//每循环五次后就删除一个
while(i<maxlen){
if(i%delspan===0){
testArray[i]=testArray[last];
delete testArray[last];
maxlen--;
last--;
}else i++;
}
//实际数组长度没变,只是被删除的都是 undefined 了,只好调一下 Array 的截取方法了
testArray.splice(last, testArray.length-last);
console.log(Date.now()-start);//打印第一个循环的耗时
// 第二个循环开始
start = Date.now();
i=0;
maxlen=testArray2.length;
while(i<maxlen ){
if(i%delspan===0) testArray2.splice(i,1);
i++;
}
console.log(Date.now()-start);//打印第二个循环的耗时
// 以下是后续增加的 用单一的数组试试 就用50万个 1024.1024 这速度你试试就知道了
// 第三个循环开始
start = Date.now();
var copyTo = [];
i=0;
maxlen=testArray3.length;
while(i<maxlen ){
if(i%delspan!==0) copyTo.push(testArray3[i]);
i++;
}
console.log(Date.now()-start);
代码是不是很简单,不简单吗,简单吗,简单的是代码,不简单的是人的想法,非要那么费劲写一个绕来绕去的,结果就是=>放弃吧,我懒得动手,我也懒得活下去。
看下面的 delete 和 splice 运行结果:
控制台是实践的好地方,它与实际的运行效果差不多,第一个数字 8 是delete
循环执行耗时 第二个数字 46 是splice
执行的耗时,以上结果是第一次 F12 打开后,输入(粘贴进去)代码运行的结果,后续再输入同样的内容,会因为缓存等其他原因影响执行,鬼知道这是为什么,还是越来越慢,尤其是splice
。看到结果是不是感到又惊喜又怀疑,其实在循环中删除元素是一个不好的写法,但弥补它的方法有很多,还有不做处理,等一个时间点再去独立吧需要删除的移除掉,或者把有用的复制下来。完了,时间不多了,早点休息,才有精力吧工作弄完,才有时间看其他的知识,才有时间去研究代码,才有能力写有用的博客,才有自己幻想的虚空世界(幻想与巧合能产生微妙的力量)。
JS Array 相关连接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array
这里也说到了,在循环中做大量的耗时操作并不推荐。
在同样的编程语言中,在循环中修改数组的长度,很容易出现问题,有时候数据并不是要循环的时候就要删除,而是等循环这一步要计算的结果完成了,才对数组做改动(一次性完成),删除操作会引发内存管理器来释放当前变量占用的内存,而释放和获取内存区域的操作是一样的,是会消耗性能的,可不要忘了,尤其是可变长度的类型,Array Object String 等。
扩展延伸 【迭代】 类似死循环
迭代 也是循环的一种
/* 平常版
一个方法多次调用自身,我先写两个方法相互调用,类似死循环
*/
function fun1(index){
if(index<10) fun2(index);
}
function fun2(index){
index++; fun1(index);
}
fun2(0); //开始
/* 灵活版
不要觉得不好就不用,有的功能使用迭代可比循环要好上几倍 案例想要吗?
别急,将来的文章会讲到的。。。
*/
var fun = function(i,_fun){
i++ ; if(i<10) _fun(i,_fun);
}
fun(0,fun);//开始
可能有些新人还没尝试这样玩过JS,但有几个月经验的同学一定都玩过,这里,每次进入方法的时候,只要使用了方法区域内的 变量,常量,对象等的声明,一定会创建新的内存索引,且一旦走出循环,内存管理器就开始执行回收释放操作,应为在这个作用域内声明的一切都不可访问,这样就成为内存管理器的执行内存回收的条件之一,除非你把其中声明的内容保存到全局变量中(作用域较为大的,如 window 上)。
说到这个写法,玩过 setTimeout
与 setTinterval
的人一定碰到过 在for
中的 延时方法中打印当前 index
的操作把 ,粗心的实验:
for(var index=0;index<10;index++) {
setTimeout(function(){
console.log(index);
},200);
}
发现打印结果都是10
,咦?什么情况。。。,其实很简单,原因是打印之前,for
已经执行完了,而index
已经++
到10了,所以延时打印出来是这样的结果,整么办呢?方法有很多,最简单的就是换个地方记录下来呗:
for(var index=0;index<10;index++){
(function(indexs){
setTimeout(function(){
console.log(indexs);
},200);
})(index);
}
这就是用了作用域的好处,更多作用域的好处等你发掘。
做的多了就都懂了,如何设计那就天高任鸟飞了,我想整么飞就整么飞,飞太高冻死我也要飞,不体验体验永远不知道高处是怎样的。
其他更有趣的内容敬请期待
未来的方向可能会有:
1.3D 使用 3D max 做好玩的东西出来
2.Three.js 这个强大的 WebGL封装库
3.VTour 插件这个好玩的项目
4.WebSocket 协议 C# 与 JS 即时通讯
5.Canvas 图形碰撞技术
6.。。。 想不到了,啥时候想起来在写吧
如有误导请联系,我会进行修正。
邮箱 hbck_gwx@qq.com