Javascript is an everchanging language. Each new spec released comes with a myriad of new features, as well as condemning some of the old paradigms we’ve come to know and love. We’ve learned to use frameworks and libraries to get around the shortcomings of the language, and many have started their education not learning the javascript language itself, but rather a widely used abstraction layer that will get replaced as the hottest new xyz toy comes along.

The ES6 spec has taken a huge step in the right direction as javascript evolves into a more advanced language with aspects pulled from more tenured object oriented languages.

I’d like to delve into a few of the most awesome features I’ve found useful in my daily javascript programming.

Blocks

We used to create closures by using Immediately Invoked Function Expressions (IIFE). With ES6, we can now create blocks which maintain their own scope.

Before

(function iife() {
  var scopedVar = 'hello world';

  console.log(scopedVar); // output: 'hello world'
})()

console.log(scopedVar) // output: undefined

After

Notice the use of let instead of var. This is a new keyword in the ES6 spec that declares a block scope local variable.

{
  let scopedVar = 'hello world';

  console.log(scopedVar); // output: 'hello world'
}

console.log(scopedVar) // output: undefined

Object Literals

ES6 allows declaring object literals by providing shorthand syntax for initializing properties from variables and defining function methods. It also enables the ability to have computed property keys in an object literal definition.

function getCar(make, model, value) {
  return {
    // with property value shorthand
    // syntax, you can omit the property
    // value if key matches variable
    // name
    make,  // same as make: make
    model, // same as model: model
    value, // same as value: value

    // computed values now work with
    // object literals
    ['make' + make]: true,

    // Method definition shorthand syntax
    // omits `function` keyword & colon
    depreciate() {
      this.value -= 2500;
    }
  };
}

let car = getCar('Kia', 'Sorento', 40000);

console.log(car.makeKia) // Output: true

Object Destructuring

Before object destructuring, we used to need temporary variables into to store and unwrap particular key-value pairs in an object.

Before

// Arrays
var arr = [1, 2, 3];
var two = arr[1];

console.log(two) // Output: 2

// Objects
var obj = {
  one: 1,
  two: 2,
  three: 3
};

var two = obj.one;

console.log(two) // Output: 2

We now have a shortcut to pluck and assign values to variables directly from arrays and objects themselves;

After

// Arrays
let arr = [1, 2, 3];
let [one, two, three] = arr;

console.log(two) // Output: 2

// Objects
let obj = {
  one: 1,
  two: 2,
  three: 3
}

const { two } = obj;
console.log(two); // Output: 2

// You can even assign an alias to the new variable to make it more semantic
const { two: numberTwo }
console.log(numberTwo) // Output: 2

Destructuring is incredibly useful when you only need to work with particular keys out of an object. It also proves to be very useful when receiving parameters in a function.

Arrow Functions

Scope is one of the more difficult concepts to grasp when first starting out with javascript. Identifying the current scope and maintaining reference to your desired scope was always a pain. ES6 helps mitigate these issues with arrow functions. Arrow functions inherit the the outer scope, removing the need for us to shadow the outer scope with a temporary variable.

Before

Seen below, the function passed to set timeout will create a new scope when executed, binding to a new lexical this. We need the _this to maintain a reference to the outer scope containing our age.

function Person(age) {
  this.age = age;
  var _this = this;

  setTimeout(function () {
    console.log(this.age) // Output: undefined
    console.log(_this.age) // Output: 5
  });
}

var p = new Person(5);

After

Using an arrow function will inherit the current scope.

function Person(age) {
  this.age = age

  setTimeout(() => console.log(this.age)) // Output: 5
}

const p = new Person(5);

Arrow functions come with a few other nifty features that I’ve found to increase the efficiency of my programming.

Single Arguments

If passing a single argument to an arrow function, parentheses are not required.

let arr = [1, 2, 3];
console.log(arr.map(val => val*2)) // Output: [2, 4, 6]

Destructuring Arguments

Stemming off the prior section on destrucuring objects, you may also do this when receiving parameters in a function. Although I’m using arrow functions here, you may also destructure parameters while using vanilla functions.

// Mimicking a reducer in the Redux library
const reducer = ({type, data, error}) => {
  console.log(type) // Output: 'CREATE_POST'
}

// Some global dispatch function
dispatch({
  type: 'CREATE_POST',
  data: {},
  error: null
});

Default Parameters

Previously, setting default parameters was a verbose and tedious process. We can now assign defaults directly when receiving the argument.

Before

function add(x, y) {
  x = x || 0
  y = y || 0
  return x + y;
}

After

const add = (x=0, y=0) => x + y;

Template Literals

Concatenating strings was honestly the worst. It was a mish mash of apostrophes and plus signs garbled together to form something that sort of looked like a string. In comes back ticks, the new syntax to define a template literal. They can span multiple lines, removing the myriad of workarounds for multi line string definition and provide easy to read string interpolation

Before

This syntax is unreadable and hard to maintain, especially when creating extremely dynamic strings.

// Plus operator
var multiLinePlus = 'This is supposed to be a ' +
'multi line string ' +
'and I usually forget the plus operator ' +
'which results in an error'

// Array + Join
var multiLineArray = [
  'This is a multi line string',
  'And I will join these strings together',
  'Using the join method with a space as the delimiter'
].join(' ');

// With a variable
var name = 'Kyle'
var stringWithVar = 'Hello ' + name + ', how are you doing?'

After

Template literals are a godsend for dynamic strings and HTML templates generated on the fly.

const name = 'Kyle'
const multiLine = `
  Ah I can write as mine lines as I want without
  having to add any extra characters to join my strings.
  And string interpolation is so easy. I just need to use dollar sign + braces
  to insert a variable into my string. Who let the dogs out?
  ${name} did.
`

The For-Of loop

Es6 provides a new way for us to iterate over arrays. This combines the power of the original for loop and the forEach Array prototype method. This gives us the current element on each iteration without using an accessor while still allowing us to break out of the loop when necessary.

Before

var arr = [1, 2, 3];

// For Loop
for (var i = 0; i < arr.length; i++) {
  console.log(arr[i]) // Output: 1, 2, 3
}

// Native forEach method
arr.forEach(function (value, key) {
  console.log(`${key}: ${val}`); // Output: 0: 1, 1: 2, 2: 3
})

After

const arr = [1, 2, 3];

for (const elem of arr) {
  console.log(elem); // Output: 1, 2, 3
}

// Obtaining the keys of the object as well
for (const [key, val] of arr.entries()) {
  console.log(`${key}: ${val}`); // Output: 0: 1, 1: 2, 2: 3
}