JavaScript

Common Syntax

Variables

// Variables types are automatic. Variable can be hoisted (use before declared)
const a = 1   // constant
let b = 2     // global variable

function foo(a, b) {
  var c = 3   // function scoped, can be redeclared (not recommended)
  let d = 4   // local variable
}

Datatypes and Operators

// Undefined: not initialized
// Falsy (false in boolean): false, 0, '', null, undefined, NaN
// Truthy (true in boolean): everything else, '0', [], {}, 1

console.log(false == ''); // true
console.log(false == []); // true
console.log(false == {}); // false

console.log([] == ''); // true
console.log([] == 0); // true
console.log({} == 0); // false


// Loose equality (below are true)
'0' == 0; null == undefined; 

// Optional Chaining Operator
const obj = { a: { b: 2 } };
console.log(obj?.a?.b); // 2
console.log(obj?.c?.d); // undefined (safe), error if c.d (danger)

// Spread Operator
const arr = [1, 2, 3];
const newArr = [...arr, 4]; // [1, 2, 3, 4]
const [first, ...rest] = [1, 2, 3];
console.log(rest); // [2, 3]


// Nullish Coalescing Operator
const value = null ?? 'default'; // Returns right-hand if left is null or undefined

Function

// Variable is passed as value, object is passed as reference
const num = 1
const obj = new Object()
const foo = function(num, obj) {
  // ...
}

// Function as argument
function higherOrder(foo) {
  foo();
  return function () {
    // ...
  }
}

// 'this' refers to the object that calls the function
function logInfo() {
  console.logInfo(this)
}

// Function can be bind to refer the object at 'this'
const item = {}
const func = logInfo.bind(item)

// Arrow function, they dont have 'this' and are anounymous
// This is the same declaration with the first function logInfo
const foo = {
  logInfo: () => {
    console.logInfo(this)
  }
}

Object and Class

// Object declaration
const obj = {
  properties1: '1',
  properties2: 2,
  func() {},
  array: [1, 2, 3]
}

// Inheritance is difference compart to other GPL
class Class {
  constructor(par) {
    this.val = par
  }
  get val() {
    return this.val
  }
  set val(vparal) {
    this.val = par
  }
  method() {}
  static staticMethod() {}
}

Data Structure

const list = [1, 2, 3]        // Array
const unique = new Set(list)  // Set
const dict = new Map([['a', 1], ['b', 2]]) // Map

Array Method for Iterations

const arr = [1, 2, 3];
const doubled = arr.map(x => x * 2); // Create new array by apply callback function
arr.forEach(x => console.log(x)); // Callback on each but did not return anything
const filtered = arr.filter(x => x > 1); // Create new array with element satisfy a condition
const found = arr.find(x => x > 1); // Returns first elment satisfies a condition
const hasGreaterThanTwo = arr.some(x => x > 2); // Return true if at least one satisfy a condition

const obj = {a: 1, b: 2, c: 3}; // Object must be converted to list to use these functions
const mapped = Object.entries(obj).map(([key, value]) => `${key}: ${value}`);

// 1. For each element, find the value that matches the id 
// 2. filter out falsy value (undefined, null, '', 0, false)
// 3. Join the result together as a string with ',' connecting 
object.map(id => {
    return ingredients.value.find(i => i.id === id)?.value || '';
})
.filter(name => name)
.join(', ');

JSON

const obj = {
  properties1: '1',
  properties2: 2,
}
obj.properties3: "3"; // Add element(property [key, value]) to json object
const objJson = JSON.stringify(obj); // Convert to JSON
const objParsed = JSON.parse('{"var1":"A","var2":"B"}');
console.log(objJson, objParsed);

Asynchronous

Asynchronous enable code to run in multithread. It is essential for API calls

API Calls

Understand API calls

// Callback function
setTimeout(() => {
  // Will run the function argument after 2 seconds
  console.log('2 second passes')
}, 2000);

// Promise, better callback when react time is unknown
const promise = new Promise(
  (resolve, reject) => {
    success = fetch('url') // async expression
    if (success) {
      resolve('success')
    } else {
      reject('failure')
    }
  }
)

// Promise method to handle respond
promise
  .then(success => {
  console.log(success)
})
  .catch(error => {
    console.log(err)
  })

// Asynchronous function, better way to deal with async
async function fetchData() {
  try {
    // Await used to wait the code until the function returns promise
    const response = await fetch("https://api.example.com/data");
    if (!response.ok) throw new Error("Network response was not ok");
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("Fetch error:", error);
  }
}

// Calling the data, since async function returns a promise
fetchData()
  .then(() => console.log("Data fetched successfully"))
  .catch((error) => console.error("Error:", error));


// Fetch multiple promises
async function fetchMultiple() {
  const urls = [
    "https://jsonplaceholder.typicode.com/users/1",
    "https://jsonplaceholder.typicode.com/users/2"
  ];

  const promises = urls.map(url => fetch(url).then(res => res.json()));
  const results = await Promise.all(promises);
  console.log("Results:", results);
}

fetchMultiple();

Working with Multiple Files

ES Module

export const a = 10;
export const b = 20;
import { a as x, b as y } from './file.js';

export default function foo(){} // Only can have one default export per file
import x from './file.js'; // No braces needed

DOM (Document Object Model)

HTML structure are defined in DOM tree model

const btn = window.document.querySelector('.button')
const btns = window.document.querySelectorAll('.button')

btn.addEventListener('click', () => {
  document.body.style.backgroundColor = 'red'
})