ES6 Syntax and Feature Overview

ECMAScript 2015, also known as ES6, introduced many changes to JavaScript. Here is an overview of some of the most common features and syntactical differences, with comparisons to ES5 where applicable.

Note: A commonly accepted practice is to use const except in cases of loops and reassignment. However, in this resource I'll be using let in place of var for all ES6 examples.

Legend

I'm not a fan of foo bar baz. Here is a key of most identifier names used throughout this reference.

  • Variable: x
  • Object: obj
  • Array: arr
  • Function: func
  • Parameter, method: a, b, c
  • String: str

Table of contents

  • Variable declaration
  • Constant declaration
  • Arrow function syntax
  • Template literals
  • Implicit returns
  • Key/property shorthand
  • Method definition shorthand
  • Destructuring (object matching)
  • Array iteration (looping)
  • Default parameters
  • Spread syntax
  • Classes/constructor functions
  • Inheritance
  • Modules - export/import
  • Promises/callbacks

Variables and constant feature comparison

I explain the concepts of scope and the differences between let, var, and const in the Understanding Variables, Scope, and Hoisting in JavaScript resource on DigitalOcean. This table provides a brief overview.

Keyword Scope Hoisting Can Be Reassigned Can Be Redeclared
var Function scope Yes Yes Yes
let Block scope No Yes No
const Block scope No No No

Variable declaration

ES6 introduced the let keyword, which allows for block-scoped variables which cannot be hoisted or redeclared.

ES5
Copy
var x = 0
ES6
Copy
let x = 0

Constant declaration

ES6 introduced the const keyword, which cannot be redeclared or reassigned, but is not immutable.

ES6
Copy
const CONST_IDENTIFIER = 0 // constants are uppercase by convention

Arrow functions

The arrow function expression syntax is a shorter way of creating a function expression. Arrow functions do not have their own this, do not have prototypes, cannot be used for constructors, and should not be used as object methods.

ES5
Copy
function func(a, b, c) {} // function declaration
var func = function (a, b, c) {} // function expression
ES6
Copy
let func = (a) => {} // parentheses optional with one parameter
let func = (a, b, c) => {} // parentheses required with multiple parameters

Template literals

Concatenation/string interpolation

Expressions can be embedded in template literal strings.

ES5
Copy
var str = 'Release date: ' + date
ES6
Copy
let str = `Release Date: ${date}`

Multi-line strings

Using template literal syntax, a JavaScript string can span multiple lines without the need for concatenation.

ES5
Copy
var str = 'This text ' + 'is on ' + 'multiple lines'
ES6
Copy
let str = `This text
            is on
            multiple lines`

Note: Whitespace is preserved in multi-line template literals. See Removing leading whitespace in ES6 template strings.

Implicit returns

The return keyword is implied and can be omitted if using arrow functions without a block body.

ES5
Copy
function func(a, b, c) {
  return a + b + c
}
ES6
Copy
let func = (a, b, c) => a + b + c // curly brackets must be omitted

Key/property shorthand

ES6 introduces a shorter notation for assigning properties to variables of the same name.

ES5
Copy
var obj = {
  a: a,
  b: b,
}
ES6
Copy
let obj = {
  a,
  b,
}

Method definition shorthand

The function keyword can be omitted when assigning methods on an object.

ES5
Copy
var obj = {
  a: function (c, d) {},
  b: function (e, f) {},
}
ES6
Copy
let obj = {
  a(c, d) {},
  b(e, f) {},
}
Copy
obj.a() // call method a

Destructuring (object matching)

Use curly brackets to assign properties of an object to their own variable.

Copy
var obj = {a: 1, b: 2, c: 3}
ES5
Copy
var a = obj.a
var b = obj.b
var c = obj.c
ES6
Copy
let {a, b, c} = obj

Array iteration (looping)

A more concise syntax has been introduced for iteration through arrays and other iterable objects.

Copy
var arr = ['a', 'b', 'c']
ES5
Copy
for (var i = 0; i < arr.length; i++) {
  console.log(arr[i])
}
ES6
Copy
for (let i of arr) {
  console.log(i)
}

Default parameters

Functions can be initialized with default parameters, which will be used only if an argument is not invoked through the function.

ES5
Copy
var func = function (a, b) {
  b = b === undefined ? 2 : b
  return a + b
}
ES6
Copy
let func = (a, b = 2) => {
  return a + b
}
Copy
func(10) // returns 12
func(10, 5) // returns 15

Spread syntax

Spread syntax can be used to expand an array.

ES6
Copy
let arr1 = [1, 2, 3]
let arr2 = ['a', 'b', 'c']
let arr3 = [...arr1, ...arr2]

console.log(arr3) // [1, 2, 3, "a", "b", "c"]

Spread syntax can be used for function arguments.

ES6
Copy
let arr1 = [1, 2, 3]
let func = (a, b, c) => a + b + c

console.log(func(...arr1)) // 6

Classes/constructor functions

ES6 introducess the class syntax on top of the prototype-based constructor function.

ES5
Copy
function Func(a, b) {
  this.a = a
  this.b = b
}

Func.prototype.getSum = function () {
  return this.a + this.b
}

var x = new Func(3, 4)
ES6
Copy
class Func {
  constructor(a, b) {
    this.a = a
    this.b = b
  }

  getSum() {
    return this.a + this.b
  }
}

let x = new Func(3, 4)
Copy
x.getSum() // returns 7

Inheritance

The extends keyword creates a subclass.

ES5
Copy
function Inheritance(a, b, c) {
  Func.call(this, a, b)

  this.c = c
}

Inheritance.prototype = Object.create(Func.prototype)
Inheritance.prototype.getProduct = function () {
  return this.a * this.b * this.c
}

var y = new Inheritance(3, 4, 5)
ES6
Copy
class Inheritance extends Func {
  constructor(a, b, c) {
    super(a, b)

    this.c = c
  }

  getProduct() {
    return this.a * this.b * this.c
  }
}

let y = new Inheritance(3, 4, 5)
Copy
y.getProduct() // 60

Modules - export/import

Modules can be created to export and import code between files.

index.html
Copy
<script src="export.js"></script>
<script type="module" src="import.js"></script>

export.js

Copy
let func = (a) => a + a
let obj = {}
let x = 0

export {func, obj, x}
import.js
Copy
import {func, obj, x} from './export.js'

console.log(func(3), obj, x)

Promises/Callbacks

Promises represent the completion of an asynchronous function. They can be used as an alternative to chaining functions.

ES5 callback
Copy
function doSecond() {
  console.log('Do second.')
}

function doFirst(callback) {
  setTimeout(function () {
    console.log('Do first.')

    callback()
  }, 500)
}

doFirst(doSecond)
ES6 Promise
Copy
let doSecond = () => {
  console.log('Do second.')
}

let doFirst = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('Do first.')

    resolve()
  }, 500)
})

doFirst.then(doSecond)

An example below using XMLHttpRequest, for demonstrative purposes only (Fetch API would be the proper modern API to use).

ES5 callback
Copy
function makeRequest(method, url, callback) {
  var request = new XMLHttpRequest()

  request.open(method, url)
  request.onload = function () {
    callback(null, request.response)
  }
  request.onerror = function () {
    callback(request.response)
  }
  request.send()
}

makeRequest('GET', 'https://url.json', function (err, data) {
  if (err) {
    throw new Error(err)
  } else {
    console.log(data)
  }
})
ES6 Promise
Copy
function makeRequest(method, url) {
  return new Promise((resolve, reject) => {
    let request = new XMLHttpRequest()

    request.open(method, url)
    request.onload = resolve
    request.onerror = reject
    request.send()
  })
}

makeRequest('GET', 'https://url.json')
  .then((event) => {
    console.log(event.target.response)
  })
  .catch((err) => {
    throw new Error(err)
  })

If you found this useful, please share!

Comments