为什么要重新写一个for循环,直接写在第一个循环里为什么不正常了?

来源:5-1 性能优化

其实TAMA酱不是我名字

2016-05-13 20:15

function updateBalls(){

for(var i = 0;i<balls.length;i++){

balls[i].x += balls[i].vx;

balls[i].y += balls[i].vy;

balls[i].vy += balls[i].g;

if(balls[i].y >= WINDOW_HEIGHT - RADIUS){

balls[i].y = WINDOW_HEIGHT - RADIUS;

balls[i].vy = -balls[i].vy*0.5;

   }

}

var cnt = 0;

   for( var i = 0 ; i < balls.length ; i ++ )

       if( balls[i].x + RADIUS > 0 && balls[i].x -RADIUS < WINDOW_WIDTH )

           balls[cnt++] = balls[i];

   while( balls.length > cnt ){

       balls.pop();

   }

       

}


写回答 关注

2回答

  • 鱼字头上一把刀
    2016-10-16 16:45:15

    刚好在写这里的代码,共同学习,互相交流啦。

    在这个函数里有三个循环。

    前两个for循环,乍一看循环条件都是一样的,貌似可以合并。我判断这两个for到底能不能合并写成一个for,主要是看他们是否互有影响。

    老师的代码中,第一个for在算小球下一个瞬间的运动位置(笼统地看,就是在计算每个球的运动轨迹),顺便用if保证了碰到画布下边界后小球将回弹。第二个for,在if中限制了小球在左边界的位置和小球在右边界的位置。即保证小球一定出现在画布上,计算所有在画布上的小球,并把它们推到数组的最前方。这里是要得到cnt的值。内容上看,这两个for循环的内容是可以合并的。

    balls[cnt++] = balls[i];

    等价于

    balls[cnt] = balls[i];
    cnt = cnt + 1;

    这里有个没有声明的默认条件,即cnt永远小于等于balls.length,也就是说,第二个for循环的内容不会改变balls.length的值,即不会影响 i 循环的次数。从逻辑上看,这两个for循环的内容也是可以合并的。所以我在代码中把两个for合并了,暂时未看到什么影响~

        // 我的代码↓
        // ps.这里的ballAmount就是老师代码中的cnt,globalHeight、globalWidth是老师代码中的画布高宽
        var ballAmount = 0;
        for (var i = 0; i < balls.length; i++) {
            balls[i].x += balls[i].vx;
            balls[i].y += balls[i].vy;
            balls[i].vy += balls[i].g;
            // 小球碰到画布下边界后向上回弹
            if (balls[i].y >= globalHeight - RADIUS) {
                balls[i].y = globalHeight - RADIUS;
                balls[i].vy = -balls[i].vy*0.75;
            }
             // 小球在左边界位置、小球在右边界位置。即保证小球出现在画布上
            if (balls[i].x + RADIUS > 0 && balls[i].x - RADIUS < globalWidth) {
                balls[ballAmount++] = balls[i];
            }
        }

    其实这也间接回答了你的问题,因为在for循环里,cnt的值是从0开始递增的,我们想得到的是画布上的出现小球总数。而balls里面放的是所有球(即画布上我们可视区域内和从画布边缘消失的不可见但存在的球)。while做的事情就是去掉balls数组中我们不可见的球,及时缩减维护数组的总长度(每个浏览器都对数组的最长值有限制的,而且数组过长还会带来性能卡顿等等问题,,),所以要等到 cnt 确定后再进行操作。举个例子,按照楼主的写法,如果while放在离他最近那个for循环里的话,第一次循环时,i=0,cnt=1,当 balls.length > 1 时删除数组末尾的项。。。balls数组。。。就会只剩第一项了吧~

  • 木须子
    2016-05-20 12:36:03

    如果要是想少写一个for,可以这样写:

        var cnt = 0;
        for( var i = 0 ; i < balls.length ; i ++ ){
          balls[i].x += balls[i].vx;
            balls[i].y += balls[i].vy;
            balls[i].vy += balls[i].g;
            if( balls[i].y >= WINDOW_HEIGHT-RADIUS ){
                balls[i].y = WINDOW_HEIGHT-RADIUS;//小球落地的位置,垂直
                balls[i].vy = - balls[i].vy*0.75;//小球弹起的速度,垂直
            }
           
            if(balls[i].x+RADIUS>0&&balls[i].x-RADIUS<WINDOW_WIDTH){
                balls[cnt++]=balls[i];
            }
        }
        
        while(balls.length>Math.min(300,cnt)){
            balls.pop();//消除数组末尾的小球
        }

炫丽的倒计时效果Canvas绘图与动画基础

学习HTML5中最激动人心的技术Canvas,彻底释放自己的创造力

96746 学习 · 1000 问题

查看课程

相似问题