@mattiacorvaglia

JavaScript cheat sheet

Arrow functions VS Regular Functions

Arrow Functions
// Single argument, single instruction
var doubles = arg => arg * 2;

// Multiple arguments, single instruction
var sum = (arg1, arg2) => arg1 + arg2;

// Multiple arguments, multiple instructions
var op = (arg1, arg2) => {
  arg1 = arg1 * 2;
  return arg1 + arg2;
}
Regular Functions
// Single argument, single instruction
function doubles (arg) {
  return arg * 2;
}

// Multiple arguments, single instruction
function sum (arg1, arg2) {
  return arg1 + arg2;
}

// Multiple arguments, multiple instructions
function op (arg1, arg2) {
  arg1 = arg1 * 2;
  return arg1 + arg2;
}

IIFE (Immediately Invoking Function Expression)

IIFE
var result = ((arg1, arg2) => arg1 + arg2)(3, 6);
Regular function invocation
function sum (arg1, arg2) {
  return arg1 + arg2;
}

var result = sum(3, 6);

Collections

Map
(Collection of key/value pairs)
var m = new Map();

m.set('key', 'value');           // Adds a new key/value pair
m.get('key');                    // Retrieves an item by key
m.delete('key');                 // Removes an item by key
m.clear();                       // Removes all items
m.has('key');                    // Returns true/false
m.size;                          // Returns the Map length
m.forEach((value, key) => { });  // Iterates all items
Set
(Collection of unique values)
var s = new Set();

s.add(23);                 // Adds new value
s.has(23);                 // Returns true/false
s.delete(23);              // Removes a value
s.clear();                 // Removes all values
s.size;                    // Returns the Set length
s.forEach((value) => { }); // Iterates all values

Objects & Arrays

Object
var o = new Object();
var o = {};
var o = {
  firstName: 'Chuck',
  lastName: 'Norris',
  age: undefined,
  power: 3000
};

o.age = 23;
o['age'] = 23;

delete o.age;
delete o['age'];
        
Array
// Create arrays
var a = new Array();
var a = [];
var a = [ 1, 1, 2, 3, 5, 8, 13, 21 ];

// Add element(s) to the end
a.push(34);
a.push(34, 55, 89);

// Add element(s) to the beginning
a.unshift(100);
a.unshift(100, 200, 300);

// Add element(s) at index
const i = 3;   // Index
const el = 34; // Element to be added
a.splice(i, 0, el);

// Remove last element
a.pop();

// Remove first element
a.shift();

// Remove element(s) by index
const i = 3; // Index
const n = 1; // How many elements
a.splice(i, n);

// Get length
a.length;

// Contains element? (true/false)
a.includes(2);

// Get index of an element
a.indexOf(5);

// Reverse order
var reversed = a.reverse();
        
Array of Object
var a = [
  { title: 'Foo', price: 10 },
  { title: 'Bar', price: 11 },
  { title: 'Baz', price: 12 }
];

// Loop through the array
a.forEach((item) => {
  console.log(item);
});

// Sort (in place)
a.sort((a, b) => {
  if (a.price < b.price) { return -1; }
  if (a.price > b.price) { return 1; }
  return 0;
});

// Filter
var filtered = a.filter((item) => {
  return item.price < 103;
});

// Map
var mapped = a.map((item) => {
  return item.title;
});

// Find (returns the first match)
var found = a.find((item) => {
  return item.price === 102;
});

// Has some (returns true/false)
var hasSome = a.some((item) => {
  return item.price < 103;
});
  
// Has every (returns true/false)
var hasEvery = a.every((item) => {
  return item.price < 103;
});

// Reduce
var reduced = a.reduce((c, item) => {
  return item.price + c;
}, 0);

Optional chaining

var foo = { name: 'Foo', details: { desc: 'Lorem ipsum.' } };
var bar = { name: 'Bar' };

console.log(foo.details.desc);    // Returns: Lorem ipsum.
console.log(bar.details.desc);    // Throws error and breaks the script execution
console.log(bar?.details?.desc);  // Returns 'undefined' and continues the script execution

Template strings

var arg = 'World';
var template = `Hello ${arg}`;
var sum = `2 + 2 = ${ 2 + 2 }`;
var multiLineString = `To be or not to be
this is the question.`

DOM manipulation

Create a DOM element
var newDiv = document.createElement('div');
Append a child element in DOM
document.getElementById('myDiv').appendChild(newDiv);
Get parent element
var parent = document.getElementById('myDiv').parentNode;

Retrieve DOM elements

Get single element (first match)
document.getElementById('foo');
document.querySelector('.foo');
Get multiple elements (all matches)
document.getElementsByClassName('foo'); // Returns live HTMLCollection[]
document.getElementsByTagName('span');  // Returns live HTMLCollection[]
document.querySelectorAll('.foo');      // Returns static NodeList[]

HTMLCollection (Array-like objects) VS NodeList (Array)

// Accessing an HTMLCollection[]
// You can use an empty array [] instead of Array.prototype
Array.prototype.forEach.call(document.getElementsByClassName('a'), function (el, index) {
  el.addEventListener('click', function (event) {
    alert(`Hello ${index}`);
    event.preventDefault();
  });
});

// Accessing a NodeList[]
document.querySelectorAll('a').forEach(function (el, index) {
  el.addEventListener('click', function (event) {
    alert(`Hello ${index}`);
    event.preventDefault();
  });
});

Store data on Browser

Local Storage
localStorage.setItem('key', 'value');
localStorage.getItem('key');
localStorage.removeItem('key');
Session Storage
sessionStorage.setItem('key1', 'value');
sessionStorage.getItem('key');
sessionStorage.removeItem('key');

Document ready

document.addEventListener('DOMContentLoaded', function () {
  alert('Document ready!');
});

Classes manipulation

document.getElementById('foo').classList.add('foo');
document.getElementById('foo').classList.add('foo', 'bar');
document.getElementById('foo').classList.remove('foo');
document.getElementById('foo').classList.remove('foo', 'bar');
document.getElementById('foo').classList.toggle('foo');
document.getElementById('foo').classList.toggle('foo', i < 10);
document.getElementById('foo').classList.replace('foo', 'bar');
document.getElementById('foo').classList.contains('foo');

Data attributes manipulation

document.getElementById('foo').getAttribute('data-foo');
document.getElementById('foo').setAttribute('data-foo', 'Hello World!');
document.getElementById('foo').removeAttribute('data-foo');

document.getElementById('foo').dataset.fooBar = 'Hello World!'; // <div id="myDiv" data-foo-bar="Hello World!"></div>
document.getElementById('foo').dataset.fooBar; // Hello World!

Setting click handler

// Multiple handlers
document.getElementById('foo').addEventListener('click', (event) => {
  alert(`Hello ${event.target.textContent}`);
  event.preventDefault();
});

// Single handler
document.getElementById('foo').onclick = (event) => {
  alert(`Hello ${event.target.textContent}`);
}

Async HTTP Request

XMLHttpRequest
const uri = 'https://example.com';

function AJAX() {
  const xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (this.readyState === XMLHttpRequest.DONE) {
      (this.status === 200) ? onSuccess(this) : onError(this);
    }
  }
  xhr.open('GET', uri);
  xhr.responseType = 'json';
  xhr.send();
}

function onSuccess(xhr) {
  console.log('HTTP Response Status Code', xhr.status);
  console.log('HTTP Response Status Text', xhr.statusText);
  console.log('HTTP Response Body', xhr.response);
}

function onError(xhr) {
  console.error('HTTP Response Status Code', xhr.status);
  console.error('HTTP Response Status Text', xhr.statusText);
}

AJAX();
Fetch
const uri = 'https://example.com';
const jsonData = { username: 'example' };
const params = {
  method: 'POST',
  mode: 'cors',
  cache: 'no-cache',
  credentials: 'same-origin',
  headers: { 'Content-Type': 'application/json' },
  referrerPolicy: 'no-referrer',
  body: JSON.stringify(jsonData)
};
fetch(uri, params)
  .then(response => response.json())
  .then(responseBody => console.log('HTTP Response Body', responseBody));
fetch(uri, params)
  .then(response => {
    if (!response.ok) { // HTTP Status Code != 2xx
      throw new Error('Server Error');
    }
    return response.json();
  })
  .then(data => console.log('HTTP Response Body', data))
  .catch((err) => console.error(err));
async function AJAX() {
  const response = await fetch(uri, params);
  if (!response.ok) { // HTTP Status Code != 2xx
    throw new Error('Server Error');
  }
  return response.json();
}

AJAX()
  .then(data => console.log('HTTP Response Body', data))
  .catch(err => console.error(err));
async function AJAX() {
  const response = await fetch(uri, params);
  if (!response.ok) {
    throw new Error('Server Error');
  }
  return response.json();
}
function onSuccess(data) { console.log('HTTP Response Body', data); }
function onError(err) { console.error(err); }

AJAX().then(onSuccess).catch(onError);
function onDone(response) {
  console.log('HTTP Response Status Code', response.status);
  if (!response.ok) { throw new Error('Server Error'); }
  return response.json();
}

function onSuccess(data) {
  console.log('HTTP Response Body', data);
}

function onError(error) {
  console.error(error);
}

fetch(uri, params).then(onDone).then(onSuccess).catch(onError);

Asynchronous JavaScript

Callback
function wait(callback) {
  setTimeout(() => {
    callback();
  }, 1000);
}

function display() {
  console.log('1000ms has passed by');
}

wait(display);
function guess(num, callback) {
  const secret = 2;
  if (num === secret) {
    callback('You guessed');
  } else {
    callback('You didn\'t guess');
  }
}

function display(result) {
  console.log(result);
  console.log('done');
}

guess(2, display);
Promise
function wait() {
  return new Promise((resolve) => {
    setTimeout(resolve, 1000);
  });
}

function display() {
  console.log('1000ms has passed by');
}

wait().then(display);
function guess(num) {
  return new Promise((res, rej) => {
    const secret = 2;
    if (num === secret) {
      res('You guessed');
    } else {
      rej('You didn\'t guess');
    }
  });
}

function display(result) {
  console.log(result);
}

guess(2)
  .then(display)
  .catch((e) => console.error(e))
  .finally(() => console.log('done'));
Async/Await
function wait() {
  return new Promise((resolve) => {
    setTimeout(resolve, 1000);
  });
}

async function waitAndDisplay() {
  await wait();
  console.log('1000ms has passed by');
}

waitAndDisplay();
function guess(num) {
  return new Promise((res, rej) => {
    const secret = 2;
    if (num === secret) {
      res('You guessed');
    } else {
      rej('You didn\'t guess');
    }
  });
}

async function guessAndDisplay() {
  try {
    const result = await guess(2);
    console.log(result);
  } catch (error) {
    console.error(error);
  }
  console.log('done');
}

guessAndDisplay();

Async/Await in series and parallel

// Return a Promise
function wait(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

// Async/Await (in series)
async function series() {
  await wait(500);      // Wait 500ms...
  await wait(500);      // ...Then wait another 500ms
  console.log('done');  // Takes 1000ms to complete, because both waits happen at the same time
}

// Async/Await (in parallel)
async function parallel() {
  const wait1 = wait(500);            // Start a 500ms timer asynchronously...
  const wait2 = wait(500);            // ...meaning this timer happens in parallel
  await Promise.all([wait1, wait2]);  // Wait for both timers in parallel
  console.log('done');                // Takes 500ms to complete, because both waits happen at the same time
}

Best practice: Manipulate virtual DOM in loops by using DocumentFragment

document.addEventListener('DOMContentLoaded', () => getData());

function getData() {
  fetch('https://example.com')
    .then(response => response.json())
    .then(responseBody => showData(responseBody));
}

function showData(data) {
  if (data.length > 0) {
    var fragment = new DocumentFragment();
    data.forEach(item => {
      const li = document.createElement('li');
      const a = document.createElement('a');
      a.href = item.url;
      a.textContent = item.title;
      li.appendChild(a);
      fragment.appendChild(li);
    });
    // Manipulate DOM just at the end
    document.getElementById('foo').appendChild(fragment);
  }
}

Best practice: Manipulate DOM using Templates

HTML
<table>
  <thead>
    <tr>
      <th>Artist</th>
      <th>Title</th>
    </tr>
  </thead>
  <tbody id="container"></tbody>
</table>

<template id="tableTemplate">
  <tr>
    <td><a></a></td>
    <td></td>
  </tr>
</template>
JavaScript
document.addEventListener('DOMContentLoaded', () => getData());

function getData() {
  fetch('https://example.com')
    .then(response => response.json())
    .then(responseBody => showData(responseBody));
}

function showData(data) {
  if (data.length > 0) {
    const template = document.getElementById('tableTemplate');
    var fragment = new DocumentFragment();
    data.forEach(item => {
      // Clone template
      var tr = template.content.firstElementChild.cloneNode(true);
      tr.children[1].firstElementChild.textContent = item.artist;
      tr.children[1].firstElementChild.href = item.url;
      tr.children[2].textContent = item.title;
      fragment.appendChild(tr);
    });
    document.getElementById('container').appendChild(fragment);
  }
}