Tip jar

JavaScript tips, tricks, and shortcuts for productivity

In this article I’ll share a few things I learned in JavaScript that I wished I had learned sooner. I’m not saying you should or shouldn’t use these techniques. Just that they exist, and understanding them will hopefully help you along.

Ternary Operations

Ternary operations allow you to simplify your conditional logic onto a nice, simple one-liner.

So instead of writing something like this:

const isHappy = true
let feelz

if (isHappy) {
  feelz = 'good'
} else {
  feelz = 'bad'
}

console.log(`I feel ${feelz}`)

We can write something like this:

const isHappy = true
const feelz = isHappy ? 'good' : 'bad'

console.log(`I feel ${feelz}`)

The only caveat is to remember that readability/maintainability is more important than slick one-liners. Ternaries can get out of hand quickly. For example:

const isHappy = true
const isHungry = false

const feelz = isHappy ? 'good' : isHungry ? 'grumpy' : 'bummed, but at least Im not hungry.'

console.log(`I feel ${feelz}`)

Type Coercion/Conversion/Casting

Type coercion (AKA. type conversion, type casting) allows you to change the variable type from one to another. For example, you could coerce a String into a Number easily without the need for functions like parseInt or parseFloat.

// String to Number by prepending with plus sign
const strNum = "123.456"
console.log(strNum) // '123.456'
console.log(+strNum) // 123.456
console.log(typeof strNum) // string
console.log(typeof +strNum) // number

// Number to String by adding empty string
const num = 123.456
console.log(num) // 123.456
console.log("" + num) // '123.456'
console.log(num + "") // '123.456'
console.log(typeof num) // number
console.log(typeof "" + num) // string

// Boolean to Number by prepending with plus sign
console.log(true) // true
console.log(+true) // 1
console.log(false) // false
console.log(+false) // 0

// Various values to Boolean with double exclamation
console.log(!!1) // true
console.log(!!0) // false
console.log(!!'hello') // true
console.log(!!'') // false
console.log(!![]) // true
console.log(!!{}) // true
console.log(!!undefined) // false
console.log(!!NaN) // false
console.log(!!null) // false

// Date to Milliseconds by prepending with plus sign
const someDate = new Date()
console.log(typeof someDate) // object
console.log(typeof +someDate) // number

“It’s not a bug, it’s a feature.”

This “feature” of JavaScript comes as a result of being a weakly-typed language. When you understand it, you can use it to your advantage. When you don’t it can lead to your dismay.

Scientific Notation

For a long time, I was unaware of JavaScript’s ability to display numbers in scientific notation. It’s nothing revolutionary, but it does save some characters from time to time.

console.log(1000000 === 1e6) // true
console.log(0.000005 === 5e-6) // true
console.log(345000 === 3.45e5) // true

Accepting Multiple Options

Every once in a while, there is the need to test the same variable against multiple possible options, and perform the same task. As with most things, there are a few approaches.

My least favorite:

if (iAm === 'sad' || iAm === 'hungry' || iAm === 'tired') {
  console.log('better do something about this')
}

A better way:

switch(iAm) {
  case 'sad':
  case 'hungry':
  case 'tired':
    console.log('better do something about this')
}

With ES6:

const options = ['sad', 'hungry', 'tired']
if(options.includes(iAm)) {
  console.log('better do something about this')
}

Short-Circuit Evaluation

Short-circuit evaluation combines logical operators (&& or ||) with expressions. I realize that doesn’t really clarify what they do, but when you look at the code it will make more sense. By using them, we can write shorter expressions.

Default/fallback values:

// old way
let favoriteFood
if (someFood) {
  favoriteFood = someFood
} else {
  favoriteFood = "pizza"
}

// new way
const favoriteFood = someFood || "pizza"

The expression above will assign favoriteFood to whatever "someFood" is. If it is defined, the left side of the OR clause will be truthy and therefore it will not need to continue execution.

If "someFood" is undefined, the left side of the OR clause will be falsy, and will continue on to the right side. Since the right side is “pizza”, favoriteFood will be “pizza”.

Optional function execution:

// old way
let bool = false
if (bool) {
 console.log('so true!')
} else {
 console.log('false!')
}

// new way
let bool = false
bool && console.log('so true!') // doesn't do anything
bool = true
bool && console.log('so true!') // logs "so true!"

Using the AND operand requires that both sides of the operation are truthy. If the left side is falsy, execution will not continue at all. If the left side is truthy, execution will continue to evaluate the right side.

All the practical applications for this may not be immediately obvious, but on place where it works well is if you write a function that takes an OPTIONAL callback function:

// old way
function doSomething(optionalCallback) {
  // Do something here...
  if(optionalCallback) {
    optionalCallback()
  }
}

// new way
function doSomething(optionalCallback) {
  // Do something here...
  optionalCallback && optionalCallback()
}

The examples above require a bit of knowledge about how JavaScript handles “truthy” and “falsy” values. You also need to be careful in how you use them because in some cases you could accidentally execute or fail to execute your functions because a value was defined but also falsy (0, null, false).

Which leads me into my last topic

Truthy and Falsy values

Boolean values (true, false) are inherently obvious whether they are true or false. But JavaScript also has values which it considers truthy and falsy. These are values which provide boolean-like behavior in a conditional statement.

Here are how the following values are treated:

// Truthy
const truthy = [
  // the boolean 'true'
  true,
  // any non-empty string
  'non-empty string',
  '0',
  'false',
  // any non-zero number
  1,
  -1,
  // any array (even empty ones)
  [],
  // any object (even empty ones)
  {},
  // any function (even empty ones)
  function(){},
]

// Falsy
const falsy = [
  // the boolean false
  false,
  // the number 0
  0,
  // an empty string
  '',
  // and these fluffs
  null,
  undefined,
  NaN
]

So instead of checking if something is sort of equal to true, we can just check if it’s truthy:

// old way
if (someString.length > 0) {
  console.log('truthy')
}

// new way
if (someString) {
  console.log('truthy')
}

Another thing to note about truthy and falsy values is that they can be a little confusing or could lead to some errors. In the case where you need strict checking whether or not a value is true of false, you can convert any value to a boolean with the double-exclamation mark:

console.log(!!"I want to be a boolean") // true

Closing thoughts

This article was intended to share some of the shortcuts I’ve picked up or seen along the way. It’s not to say that these are the best ways to implement the logic.

None of these patterns will make you a better developer, or make your code faster, or anything like that. In fact, with the wrong implementation, you could actually make things more complicated, buggy, or error-prone.

There is also the matter of coding style. If you don’t like how these code samples look, don’t use them. As with any code, the practices you choose to employ should make sense for you, your team, and the maintainability of the project.

The main point is to recognize and understand these patterns. Whether you choose to use them is up to you, but you may run into them in someone else’s code base, and you will be better off for knowing how they work.