I came across this small JavaScript Program (on Khan Academy) written by someone else:
/*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]);
}
};
I looked at the code and found it a bit difficult to read. So I decided to make my own version with some object orientation:
// apparently, object orientation is a lot slower than just putting the data in arrays
var Point = function(x, y) {
this.x = x;
this.y = y;
this.moving = true;
};
// static constant
Point.dirs = [
{x:0, y:1},
{x:1, y:0},
{x:0, y:-1},
{x:-1, y:0}
];
/*vars*/
frameRate(0);
var Sz=100;
var particles=1000;
scale(400/Sz);
// first point
var points=[new Point(floor(Sz/2), floor(Sz/2))];
points[0].moving = false; // blue
// remaining points
for(var i=0;i<particles;i++){
points.push(new Point(floor(random(0, Sz)), floor(random(0, Sz))));
}
var l=points.length-1;
/*functions*/
var move = function(p1){
var mv = Point.dirs[floor(random(0,4))];
var notAttached = true;
for(var i = l; i >= 0; i--) {
if(!points[i].moving && points[i].x === p1.x + mv.x && points[i].y === p1.y + mv.y) {
notAttached = false;
p1.moving = false;
i = 0;
}
}
if (notAttached) {
p1.x += mv.x;
p1.y += mv.y;
if (p1.x < 0) { p1.x = 0; }
if (p1.x > Sz) { p1.x = Sz; }
if (p1.y < 0) { p1.y = 0; }
if (p1.y > Sz) { p1.y = Sz; }
}
};
/*draw*/
draw= function() {
background(255);
for(var i=points.length-1; i >= 0; i--) {
stroke(0);
if (points[i].moving) {
move(points[i]);
}
else {
stroke(0, 0, 255);
}
point(points[i].x, points[i].y);
}
};
The original just uses arrays for data. Index [0]
is an x coordinate, index [1]
is a y coordinate, index [2]
is a flag.
I think the only changes I made were just what was needed to replace point[0]
with point.x
, etc.
but I was surprised by how much slower my version was.
Is there a better way to make the code more readable without losing performance? or do we have to lose performance for readability?
JavaScript Engine: Chrome in Windows 10
Edit: more information discovered:
As Ryan pointed out, using plain objects instead of a Point
class – new Point(x, y)
→ {x: x, y: y, moving: false}
- improved performance close to the original. So it was just the Point
class that made it slow.
So now working with 3 different versions of the program:
In Chrome, the array data and plain object have no easily noticeable difference in performance, the Point class is noticeably slower.
I installed Firefox to test it, and found all three versions to be close to the same performance as each other.
Just eyeballing it, the Firefox speed seems to be in between the slow and the fast speeds I get from Chrome, probably closer to the fast end.
JavaScript has been evolving into a more readable language. There is no doubt about that, and there is no harm either. Software development is a dynamic market where teams change constantly, meaning that the code needs to be readable for newcomers.
That is why people use bundlers like webpack to make readable code more efficient. Checkout https://webpack.js.org/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With