Skip to content

Modern ECMAScript cheat sheet

Marwane Kalam-Alami edited this page Jul 21, 2020 · 1 revision

Here are some modern language features we use widely in the code.

Variable declarations

let x = 5 // `let` is "block-scoped" thus more predictable than `var`
const y = 5 // `const` preferred for imports and other variables that won't change

Quick object building

const a = 1
let abc = {
  a, // ⚠️ no need to write "a: a"
  b: 2,
  c: 3
}
let abcd = {
  ...abc, // ⚠️ this is called "spreading"
  d: 4
}

Arrow functions

// doStuff(callback)

doStuff(a => {
  console.log(a)
})
doStuff(a => console.log(a))
doStuff(() => console.log("hello world"))
doStuff(() => 5) // returns 5
doStuff(() => ({ a: 5 })) // ⚠️ returning an object requires parentheses

function thisTest() {
  this.x = 5
  const arrowFunction = () => {
    console.log(this.x)
  }
  arrowFunction() // ⚠️ will print 5 because arrow functions do NOT bind `this`
}

Destructuring

let arr = [ 1, 2, 3 ]
let obj = { a: 1, b: 2, c: 3 }

let [ a, , c ] = arr // a=1, c=3
let { a } = obj // a=5

Promises

Without await/async

We don't use this syntax a lot, but it's still useful to understand how Promises actually work. await/async is just pretty syntax for the actual Promises API.

async function A() { /* stuff returning promises */ }
async function B(resultOfA) { /* stuff returning promises */ }

// Do A, wait for the result, then render the page.
function example() {
  A().then(a => {
    render('page', { a })
  })
}

// Do A then B, wait for both results, then render the page.
// Handle errors.
// This is getting not very readable.
function example() {
  A().then(a => {
    return B(a).then(b => { // `return` needed to catch errors from B
      render('page', { a, b })
    })
  }).catch(e => {
    render('error', e)
  })
}

With await/async

async function A() { /* stuff returning promises */ }
async function B(resultOfA) { /* stuff returning promises */ }
async function C() { /* stuff returning promises */ }

// Do A, wait for the result, then render the page.
async function example() {
  const a = await A()
  render('page', { a })
}

// Do A then B, wait for both results, then render the page.
// Much better than without async/await.
async function example() {
  try {
    const a = await A()
    const b = await B(a)
    render('page', { a, b })
  } catch (e) {
    render('error', e)
  }
}

// Do C but without waiting for it to end.
// Here `c` will hold a Promise and not be usable in the template.
async function example() {
  const c = C()
  render('page')
}

// A more complex scenario: we want to do A then B,
// but at the same time run C in parallel to gain time.
// And we still want to gather the result of all three.
async function example() {
  const aThenB = A().then(async function(a) {
    return { a, b: await B(a) }
  })
  let [ aAndB, c ] = await Promise.all([aThenB, C()])

  render('page', {
    ...aAndB,
    c
  })
}