Update: I made a library, parse-md, out of some of this behavior in order to address the need of parsing metadata from markdown files.
My latest problem to solve was how, once I had a
.md (Markdown) file’s contents, to go about parsing out the blog post’s metadata (see below: the key/value pairs between the two
split this file based on newlines, I needed a way of finding the indices of the metadata boundary,
---, so that I could
splice the array in to two pieces and be on my way. My first attempt at getting the indices looked like this:
This is a simple solution that any junior dev can do, and it accomplishes the task… but it doesn’t feel right. I am iterating over each item, testing each line and mutating an array variable when a condition is true. While it doesn’t look like much, that is a good bit going on all at once. Instinct tells me that each action could be its own simple method. I also don’t want to use a temporary variable that I mutate. However, this removes
forEach from our options, as
forEach returns the original array.
map() to the rescue! (or so we think).
Crap. Because I only return when the test is true,
map doesn’t know what to return, so it returns
undefined and moves on. It would be nice if we could clean out these
Cleaning Up Our Array
How can we achieve the following desired functionality?
Let’s make a function on the
Here, we access
prorotype and add our own custom method,
clean and pass it one argument. Next, we need to
filter out all of the
undefineds in our array.
But what if we need to clean more than one value out? What if we need to clean
arguments object, which looks like an
Array but is not. For example, this code will give you an error about
indexOf not being defined on
arguments is very similar to an array — how can we get this to work?
slice to the rescue!
Without any additional arguments,
slice makes a copy of an array and allows us to provide a custom receiver of array-like functionality:
arguments. What is returned from the second line above is an array-ized copy of
arguments. Now that
args is an array of all the arguments that are passed to
clean, we can pass as many options as we would like to clean out our array!
Here is more example usage of such a method:
In attempting to refactor some fairly simple, though multiple-responsibility code, we end up creating a few reusable functions that will benefit us in the future, and we make our code more maintainable, testable and readable in the end. Here it is once we have finished:
But could this be done even simpler?
p.s. Use reduce next time
You may have been wondering why we didn’t use
reduce like this from the start:
or, cleaned up a bit,
Surprise! We totally could have, but since
reduce was not our first thought when refactoring, we managed to solve our problem in another way. There are 1000 ways to solve problems, and sometimes you don’t think of the best one first, but you can still make the best with what you have at the time and refactor later.