Five ES6 features to make your life easier

Learning new syntax is a weird thing. Most of us pick up the bare minimum that we need to be productive, and then occasionally when watching a friend/colleague/instructor code, we stumble upon new tricks that make us wonder how we survived without them.

The below list is 5 such little shortcuts that will make your coding life a little faster.

As always, if this article is useful to you, please recommend and share!

Tagged template literals

Template literals! They’re great. No longer will we do this…

const concatenatedString = “I am the “ + number + “ person to recommend this article.”

… when we can do this…

const concatenatedString = `I am the ${number} person to recommend this article.`

Wow. So nice.

Tagged template literals allow us to take this convenience one step forward — and invoke a function with a string.

Watch:

const consoleLogAString = (string) => {
console.log(string)
}
consoleLogAString`I am the string to be logged!`
// I am the string to be logged!

In other words, this:

consoleLogAString('Here is the string!')

… is the same as this:

consoleLogAString`Here is the string!`

Tagged template literals have an additional advantage: the target function is passed an array of arguments generated from the string. These arguments are arranged like so: first, an array of strings surrounded interpolated values, then each interpolated values.

Let’s see an example:

function logOutValues(strings, value1, value2) {
console.log(strings, value1, value2)
}
logOutValues`Here is one value: ${1} and two: ${2}. Wow!`
// ["Here is one value: ", " and two: ", ". Wow!"] 1 2

You can do so for as many interpolated values as needed, even manipulating a string like so:

const person = {
name: "Scott",
age: 25
}
function experience(strings, name, age) {
  const str0 = strings[0]; // "that "
const str1 = strings[1]; // " is a "
  let ageStr = 'youngster'; 
if (age > 99){
ageStr = 'centenarian';
}
  return str0 + name + str1 + ageStr;
}
const output = experience`that ${ person.name } is a ${ person.age }`;
console.log(output);
// that Scott is a youngster

(Thanks to Domenico Matteo for clarification on this section.)

This feature also lets you embed DSL’s with escape sequences (more on that here).

How Is This Useful?

It’s a cleaner way to invoke functions with strings. It makes it easier to interpolate, and to create new strings based on interpolated strings.

For an example of this in the wild, check out the styled-components library for React:

const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;

Implicit return

How many times do you write a function that returns a value?

const addOne = (num) => {
return num + 1
}
console.log(addOne(1))
// 2

Answer: all the fricking time.

Swap those squiggly brackets for normal brackets, and take advantage of implicit return:

const addOne = (num) => (
num + 1
)
console.log(addOne(1))
// 2

Let’s take it one step further!

const addOne = num => num + 1
console.log(addOne(1))
// 2

How Is This Useful?

Less code. Better readability.

May even encourage you to write smaller functions, just so you can avoid multi-lines.

At the end of the day, though, it’s just pretty.

Argument destructuring WITH default arguments

If you haven’t heard about argument destructuring, you’re missing out.

const person = { name: 'Scott', attractiveness: 8.5 }
const consoleLogAttributes = ({ name, attractiveness }) => {
console.log(name, attractiveness)
}
consoleLogAttributes(person)
// 'Scott', 8.5

So useful.

But what if we invoke the above function with no arguments?

consoleLogAttributes()
// TypeError: Cannot match against 'undefined' or 'null'.

Lame. Let’s save this error by setting a default argument of an empty object:

const consoleLogAttributes = ({ name, attractiveness } = {}) => {
console.log(name, attractiveness)
}

Now:

consoleLogAttributes()
// undefined undefined

If we don’t call consoleLogAttributes with any argument, we don’t get an error anymore! Why don’t we take it one step further, though…

const consoleLogAttributes = ({ 
name = 'Default name',
attractiveness = '10'
} = {}) => {
console.log(name, attractiveness)
}

Defaults everywhere. This means both the below will yield the same results:

consoleLogAttributes()
// 'Default name', 10
consoleLogAttributes({})
// 'Default name', 10

So we’ll always have SOME value produced.

How Is This Useful?

Your functions will be more resilient, since they can adapt to being passed undefined arguments.

The downside is the visual clutter in the function declaration above, but most of the time this is a small price to pay for more graceful fallbacks.

Property value shorthand (including functions)

Let’s go back to the person object above.

Here’s a common pattern: you have a variable (called, for example, name), and you want to set a key called name to the value of name.

const name = "Scott"
const person = { name: name }
// { name: "Scott" }

Thanks to ES6, you can do this instead:

const name = "Scott"
const person = { name }
// { name: "Scott" }

Aaaaand do this with multiple values…

const name = "Scott"
const programmingAbility = "poor"
const person = { name, programmingAbility }
// { name: "Scott", programmingAbility: "poor" }

Aaaaaaaaand even do it with functions…

const name = “Scott”
const sayName = function() { console.log(this.name) }
const person = { name, sayName }
// { name: “Scott”, sayName: function() { console.log(this.name) } }

And and and do the function declarations right within the object declaration:

const name = “Scott”
const person = { name, sayName() { console.log(this.name) } }
// { name: “Scott”, sayName: function() { console.log(this.name) } }

How Is This Useful?

Write less code. Write cleaner code.

Map()

Let’s say you have an object with a hundred key-value pairs. You want to loop through each one and console log out the value.

This is what you have to do:

const targetObject = { 1: 'one', 2: 'two' }
Object.keys(targetObject).forEach(key => {
console.log(targetObject[key])
}
// 'one'
// 'two'

That’s a little awkward.

The issue is that objects are not iterable — so you can’t loop over its properties.

If only there was an iterable version of an object…

const map = new Map([[1, 'one'][2, 'two']])
map.forEach(val => {
console.log(val)
}
// 'one'
// 'two'

Say hello to ES6 maps. In the above, we create a map by passing the constructor an array of key-value pairs.

This will form a map like so:

Map(2) {1 => "one", 2 => "two"}

You can access and modify these values using get and set:

map.get(1)
// 'one'
map.set(3, 'three')
// Map(3) {1 => "one", 2 => "two", 3 => "three"}

But maps are also iterable, meaning you can using array methods like forEach and map to loop over their values.

You can also easily grab their size, unlike objects:

const objectSize = Object.keys(object).length
const mapSize = map.size

Lastly, you can use ANYTHING as keys for a Map, unlike an object: dates, functions, objects… You can thus have a Map with keys as dates, which return data relevant to that particular calendar day.

How Is This Useful?

Maps act a lot like objects, but with added array-like functionality.

These leads to cleaner, simpler interaction than with plain objects, and also the very explicit get and set commands.

There’s also the flexibility of setting anything as the key, letting you organize Maps however you wish.

Done!

If this article has been any use to you, please hit that green heart and share it with your friends.

Thanks for reading!

(Want to stay up to date/learn best practices for the future of web development? Say hello to Progressive Web App Newsletter — subscribe below.)