snippet #3 - chainable logger

Nov 8, 2019
2 minutes to read

As functional programming becomes more popular in the JavaScript realm, so do Higher-Order Functions and us constantly depending on .filter(), .map(), .forEach(), and friends to modify our data.

As a lover of terse JavaScript, I often use the shorthand return pattern for fat-arrow functions, such as

const paidPlans = plans.filter((plan) => plan.subscriptionId)

// Instead of 👇
const paidPlans = plans.filter((plan) => {
  return !!plan.subscriptionId
})

Even though the first approach is aesthetic for me personally and reads nicely when chained with other Higher-Order Functions (like .map()), it has a major drawback when it comes to debugging.

This should now be the part where I preach about using your browser’s developer tools correctly, firing up those breakpoints and stepping through your code. But I’m a realist. Either you’ve never took the time to learn to use breakpoints & the Sources tab, or you’re thinking that this quick anomaly has to have a simple reason and it’s not worth the effort of breakpoints. But you already know how it goes…

Now that we’ve established that console.log is that goofy friend you’re ashamed of (but still call up when you have nothing to do on a Friday night), why not learn to reap more value from it? The main idea is to keep the chainability. Therefore, we need to return the same array/value that it’s called upon. Let’s not modify the prototype directly, since then it would get looped over with for (a in array), but we can use Object.defineProperty():

Object.defineProperty(Array.prototype, 'log', {
  value: function () {
    this.forEach((item) => console.log(item))
  },
})

And now it’s a breeze to check whether or not an array contains the right data. No more interim variables or having to write explicit return statements since you had to call console.log on the line above 😬 Rejoice!

const newArray = oldArray
  .sort(someSortMethod)
  .filter((i) => i.quantity > 5)
  .log() // Wooh - found my mistake in seconds!
  .map((i) => i.name)