可读性越高的JavaScript代码速度越慢?

可读性越高的JavaScript代码速度越慢?,javascript,performance,oop,Javascript,Performance,Oop,我遇到了(关于汗学院)其他人写的: /*vars*/ frameRate(0); var Sz=100; var particles=1000; scale(400/Sz); var points=[[floor(Sz/2),floor(Sz/2),false]]; for(var i=0;i<particles;i++){ points.push([floor(random(0,Sz)),floor(random(0,Sz)),true]); } var l=points.len

我遇到了(关于汗学院)其他人写的:

/*vars*/
frameRate(0);
var Sz=100;
var particles=1000;
scale(400/Sz);
var points=[[floor(Sz/2),floor(Sz/2),false]];
for(var i=0;i<particles;i++){
    points.push([floor(random(0,Sz)),floor(random(0,Sz)),true]);
}
var l=points.length-1;
var dirs=[[0,1],[1,0],[0,-1],[-1,0]];
/*functions*/
var move=function(p1){
    var mv=dirs[floor(random(0,4))];
    var temp=true;
    for(var i=l;i>=0;i--){
        if(!points[i][2]&&points[i][0]===p1[0]+mv[0]&&points[i][1]===p1[1]+mv[1]){
            temp=false;
            p1[2]=false;
            i=0;
        }
    }
    if(temp){
        p1[0]+=mv[0];
        p1[1]+=mv[1];
        if(p1[0]<0){p1[0]=0;}
        if(p1[0]>Sz){p1[0]=Sz;}
        if(p1[1]<0){p1[1]=0;}
        if(p1[1]>Sz){p1[1]=Sz;}
    }
};
/*draw*/
draw= function() {
    background(255);
    for(var i=points.length-1;i>=0;i--){
        stroke(0);
        if(points[i][2]){
            move(points[i]);
        }
        else{
            stroke(0,0,255);
        }
        point(points[i][0],points[i][1]);
    }
};
/*变量*/
帧率(0);
var Sz=100;
var粒子=1000;
比例(400/Sz);
var点=[[楼层(Sz/2),楼层(Sz/2),假];
对于(变量i=0;i=0;i--){
如果(!点[i][2]&点[i][0]==p1[0]+mv[0]&点[i][1]==p1[1]+mv[1]){
温度=假;
p1[2]=假;
i=0;
}
}
如果(临时){
p1[0]+=mv[0];
p1[1]+=mv[1];
如果(p1[0]Sz){p1[0]=Sz;}
如果(p1[1]Sz){p1[1]=Sz;}
}
};
/*画*/
draw=函数(){
背景(255);
对于(变量i=点。长度-1;i>=0;i--){
冲程(0);
若有(第[i][2]点){
移动(点[i]);
}
否则{
冲程(0,0255);
}
分值(分值[i][0]、[i][1]);
}
};
我看了一下代码,发现有点难读。所以我决定:

//显然,面向对象比仅仅将数据放入数组要慢得多
变量点=函数(x,y){
这个.x=x;
这个。y=y;
这是真的;
};
//静态常数
Point.dirs=[
{x:0,y:1},
{x:1,y:0},
{x:0,y:-1},
{x:-1,y:0}
];
/*瓦尔斯*/
帧率(0);
var Sz=100;
var粒子=1000;
比例(400/Sz);
//第一点
var点=[新点(楼层(Sz/2)、楼层(Sz/2))];
点[0]。移动=假;//蓝色
//剩余点
对于(变量i=0;i=0;i--){
如果(!points[i].移动和点[i].x==p1.x+mv.x和点[i].y==p1.y+mv.y){
notAttached=false;
p1.1=假;
i=0;
}
}
如果(未附加){
p1.x+=mv.x;
p1.y+=mv.y;
如果(p1.x<0){p1.x=0;}
如果(p1.x>Sz){p1.x=Sz;}
如果(p1.y<0){p1.y=0;}
如果(p1.y>Sz){p1.y=Sz;}
}
};
/*画*/
draw=函数(){
背景(255);
对于(变量i=points.length-1;i>=0;i--){
冲程(0);
if(点[i]。移动){
移动(点[i]);
}
否则{
笔划(0,0,255);
}
点(点[i].x,点[i].y);
}
};
原始版本只使用数组来存储数据。索引
[0]
是x坐标,索引
[1]
是y坐标,索引
[2]
是标志。 我认为我所做的唯一更改就是用
point.x
等替换
point[0]
。 但令我惊讶的是,我的版本慢了很多

有没有更好的方法使代码更具可读性而不损失性能?还是我们必须为了可读性而失去性能

JavaScript引擎:windows10中的Chrome

编辑:发现更多信息:

正如Ryan指出的,使用普通对象而不是
类–
新点(x,y)
→ <代码>{x:x,y:y,moving:false}-性能接近原始版本。因此,正是
类让它变慢了

因此,现在使用3个不同版本的程序:

  • 阵列数据(原始)
  • 点类(第一次重写)
  • 普通对象(第二次重写)
在Chrome中,数组数据和普通对象在性能上没有明显差异,Point类的速度明显较慢

我安装了Firefox进行测试,发现这三个版本的性能几乎相同


只要看一眼,Firefox的速度似乎介于我从Chrome获得的慢速和高速之间,可能更接近快速端。

这就是为什么人们使用像webpack这样的捆绑包来提高可读代码的效率。签出

确保您不是唯一看到/将看到此代码的程序员(可能有些程序员是初学者,甚至很难理解代码)

对于您的代码,我将选择可读性而不是性能

我会扔掉这个和新的。 这是全局对象还是未定义?从你的例子我看不出来!你必须知道你所处的环境

过早优化是万恶之源。唐纳德·克努斯

浏览器在优化我们编写的代码方面已经变得非常出色

您可以使用performance.now()测试程序的速度,它非常准确:

var t1 = performance.now() 
//your code
var t2 =  performance.now()
console.log(t2-t1);
或者可以使用jsperf()。我肯定还有其他几个网站有这个设施


JLRishe的评论很好:我完全同意

您如何测试性能?“只跑一次还是多跑几次?”艾弗里只是在观察画布上点的移动。每次运行几次都会产生明显的差异。哪个浏览器?另外,尝试普通对象–
新点(x,y)
→ <代码>{x:x,y:y,moving:false}。(FWIW,性能在Firefox 57上看起来是一样的。)@Ryan使用普通对象将性能恢复到原来的水平(或者至少接近,没有明显的区别)。所以我猜这只是原型使它变慢了?专业提示:将
改为返回对象的函数。然后去掉
新的
。然后,您可以使用无负担的普通对象,其余代码可以保持完全相同:
函数点(x,y){return{x:x,y:y,moving:false};}。。。。点推(点(地板(随机(0,Sz)),地板(随机(0,Sz)))
var t1 = performance.now() 
//your code
var t2 =  performance.now()
console.log(t2-t1);