JS 中 delete 与 splice 与 循环

2023-11-16

【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 运行结果:

console

运行结果
控制台是实践的好地方,它与实际的运行效果差不多,第一个数字 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 上)。
说到这个写法,玩过 setTimeoutsetTinterval 的人一定碰到过 在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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JS 中 delete 与 splice 与 循环 的相关文章