Javascript

Basics

false && "hi" -> false
true && "hi" -> "hi" (returns the last value)

Variables

Naming:

Should be declared only once (in its scope).

let x = 5; // block-scoped
x = 3;
const X = 1; // block-scoped
// X = 3; error // can't be reassigned

var y = 0; // global- or function-scoped. Avoid.

Fundamental Objects

Operators

Plus (+)

The + operator returns the numeric representation of the object.

Value +Value
1 ‘-1’ ‘3.14’ ‘0xAA’ true false null ‘Infinity’ ‘infinity’ undefined 1 -1 3.14 170 1 0 0 Infinity NaN NaN

Spread operator (…)

Clones the object.

let xs = [1,2,3];
let ys = [...xs];

let x = { key: "value"};
let y = {...x}

Null operators

let x = nullable?.prop ?? 'default';
let y ??= 1;

Control Flow

Conditional

ternary:

condition ? exprIfTrue : exprIfFalse;

Iteration

const arr = [3, 5, 7];
for (var key in arr) {
  console.log(key); // logs "0", "1", "2"
}

for (var val of arr) {
  console.log(val); // logs "3", "5", "7"
}

Functional

Array Sum

const inputs = [1, 2, 3];
let square = (x) => x * x;

var sumSquares = inputs.map(square).reduce((sum, x) => sum+x, 0);

// like range(0, N) in Python
// fill is needed for map to work
Array(N).fill().map((_, i) => i);

Events

Strings

Template literals

let x = `three = ${1+2}`;
const classes = `header ${
  isLarge() ? "" : `icon-${item.isShown ? "hide" : "show"}`
}`;

// Tagged templates
function myTag(strings, ...values) {
  console.log(strings, values);
}
const x = 3;
const output = myTag`This is ${x}`;
// is equivalent to
myTag(["This is ", ""], [3])

Arrays

Array.from(otherObj)

let xs = [11, 2, 1];
xs.sort() // is incorrect! JS converts to string before sorting
xs.sort((a,b) => a - b)
xs.reverse()

xs.map((x, i, arr) => { /* ... */ })
xs.filter((x, i, arr) => ...) // arr is the intermediate array

xs.some(x => x > 0) // like Python's `any`
xs.every(x => x > 0) // like Python's `all`


xs[i] = x // mutates
xs.with(i, x) // copies

xs.push(x) // mutates; insert at end
xs.unshift(x)  // mutates; inserts at start
xs.concat(ys [,zs,...]) // copies and returns new array

xs.pop() // mutates; remove at end
xs.shift() // mutates; remove at start

xs.slice(i [,n])  // returns n items from i onwards
xs.splice(i [,n, [a, b, ...]])  // mutates; removes, returns n items from i onwards; inserts items

Objects

let user = new Object(); // "object constructor" syntax
let user = {};  // "object literal" syntax

let user = {     // an object
  name: "John",  // by key "name" store value "John"
  age: 30        // by key "age" store value 30
};

user["name"] = user.name;
user.no === undefined;
no in user === false;

const { name, age } = user; // object destructuring

const myObject = {
  first: "one",
  second: "two",
};

for (const [key, value] of Object.entries(myObject)) {
  console.log(key, value);  // first one, second two
}
// Object.keys(), Object.values()

Classes

class Person {
  name;
  constructor(name) {
    this.name = name;
  }

  introduceSelf() {
    console.log(`Hi! I'm ${this.name}`);
  }
}

class Kid extends Person {
  constructor() {
    super();
    console.log(this);
  }
}

Set

s = new Set([1, 2, 3])
s.add(x)
s.has(x)

Date

Date() // string
new Date() // date
new Date(year, monthIndex, day) // date
new Date(unixMs) // date

date.getTime() // unix ms
date.setTime(unixMs)
Date.UTC(year, monthIndex, day) // unix ms

Document object model

let elementArray = document.getElementsByClassName("class-name");

element.className = "class-x";
element.classList.add("class-x");
// contains('x') -> bool
// item('x') -> int index
// remove('x')
// toggle('x') -> bool; add if not exists [true], remove if exists [false]


let input = getInputField();
input.value = "x";

let button = getButton();
button.click();

document.querySelectorAll("a") // get all <a> types
document.querySelectorAll("div.note, div.list") // get all <div> of class note or list

// creating a link
let a = document.createElement('a');
a.innerHTML = someHTML;
a.textContent = "text"; // innerText is slower and confusing
a.title = "my title text";
a.href = "http://example.com";

Script tags are executed in the order they appear. When a script tag executes, everything above it in the DOM is available. So, if script is defined in the head, then body is not available. Can defer script execution by using <script defer src="min.js"></script>

Script tags which are dynamically added to the page via the DOM are executed by the browser:

var x = document.createElement('script');
x.textContent = 'alert("hi")';
document.head.appendChild(x);

Script tags which are dynamically added to the page via innerHTML are not:

document.head.innerHTML += '<script>alert("hi")</script>';

Tables

var table = document.getElementById("table");
var tr = table.insertRow(0);
var td1 = row.insertCell(0);
var td2 = row.insertCell(1);
td1.innerHTML = "x";

Promises

You can’t get the data synchronously out of a promise. Have to use x.then() or await x.

fetch()
    .then(x => x.json()) // .json() itself returns a promise
    .then(x => {log(x); print(x);})
    .catch(error => console.log(error.message))
    .then(x => console.log("will run even if error in prev thens"))
    .then(onFulfilled, onRejected) // e.g. then(() => 5, () => 0)

RegExp

let re = RegExp("\s*hi");
re.compile()
re.test(" ho") // false
re.exec("hilo") // ["hi"]

// ignore case
RegExp("hi").test(" HI", "i") // true

// avoid .compile()

Storage

The Storage can only handle strings.

var names = ["a"];
localStorage.setItem("names", JSON.stringify(names));
var storedNames = JSON.parse(localStorage.getItem("names"));

Misc

Keys

event.key === "Enter"

URLs

thisURL = document.URL;
const url = new URL("eg.com");
url.search = new URLSearchParams({foo: "bar"}); // use search, not searchParams
// or
url.searchParams.append("foo", "bar");

https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore

Sleep

await new Promise(r => setTimeout(r, 1000));

Snippets

https://phuoc.ng/collection/1-loc/

Bundling

https://jakelazaroff.com/words/an-extremely-simple-react-starter-kit/#implementation

References

Worth reading: