Making a Simple D3 Visualization &The Stupid JS Mistakes I Made

Data…but where are the trends?? (Source: https://www.pexels.com/)

I wanted to make a visualization: specifically, I wanted to create a bar chart of some data. In doing so, I used JavaScript again for the first time in a while and learned a few cool new lessons.

[1, 2, 3, 4, 5, 10, 11, 12].sort() is [1, 10, 11, 12, 2, 3, 4, 5]

It turns out if you read the docs you will find that JavaScript, when compared to Python, has an unexpected result when you call .sort() on an array of ints: You will be sorting those members by their Unicode equivalent. MDN Sort Docs told me this, simply and clearly. I needed the min and max of an array and (ok, yes, this is bad) just sorted the thing and took the first and last element. Yes, I get it, this is bad, but it was really weird that I got a different value from var m = d3.min(arrayThing) than from x.sort(); var m = x[0], which led me to learn about this.

Side Note: Sorting an array to get the min and max is bad because you reassign so many variables on a journey to simply assign the two items you really want: the min and the max.

JavaScript passes objects by copy-reference

One of my functions took a big array from another function, then chopped it up and sometimes overwrote the occasional entry in this array. Imagine my dismay when I realized if I called this function a second time or used the array again after this function had mangled it, the data had changed!

I checked this StackOverflow answer first. Primitives by copy, objects by “copy of reference”. My takeaway from this is — hopefully not bad — that you need to clone the object if you want to mutate it in your function.

There is certainly more to discuss here: scope, passing arguments, etc. If you have comments, I am all ears. Hit me up on Twitter or here on Medium.

Copying Objects by Serializing & Deserializing in JSON is a Bad Idea™

After I discovered that passing by reference would have an impact on my code, I settled on cloning the object. This didn’t feel great, but I saw this StackOverflow answer on Efficiently Cloning JS Objects, should have realized “Efficiency” wasn’t the main target I was shooting for. One important thing I overlooked until a second reading was that the author of that comment mentions Date conversions would not work in this case.

In general, I disliked this practice because even if you don’t use Date objects, which I did, it limits you to not using Date objects in the future and additionally I feel like (but do not have conclusive evidence to support) that this may not be kind in other edge cases. Here is one, you decide if you would ever do this:

Bad effects from doing something silly

undefined is not your friend

At some point, my code contained something like this:if (blah.lengt === 0)which somehow made it through multiple iterations of running the script and checking the output. JavaScript is flexible in that it doesn’t completely throw a fit if you try to access things that don’t exist — it simply returns a gentle undefined and goes on about it’s business.

This is something I need to watch out for more, I’ve included linting in my workflow now, but read on to find the real solution…

Most of these problems could have been solved by Unit Tests

Sometimes when we start a project, we think it’ll be so quick and easy to finish it that we can just write a few functions, strap them together and see our results. Nothing could have been farther from the truth in this instance.

Maybe because I did this outside work I was more rushed and felt like I couldn’t dedicate the time to testing, but I was wrong.

  • Had I written a unit test to cover the calculation of the domain of my graph, I would have caught that nasty min/max bug earlier.
  • Had I written a unit test to cover the splitting of segments, I would have discovered that I flipped the ratio numerator and denominator very quickly.
  • Indeed, I would have discovered that the output from a number of functions was off or incorrect in a number of situations and for this reason, I regret not writing unit tests for the code.

In the next week or so, look for more unit tests in my project, most likely with MochaJS.

And for reading so far, here is a graph of my 50 mile run, with average speed bucketed into smaller time segments so it’s easier to see general trends across the graph.

50 mile run: time vs speed (m/s)

Here’s a link to the repo — you are welcome to contribute PRs for anything you desire (even formatting!) and if anything doesn’t make sense, please do reach out to me.