JS Fiddle
JS Fiddle is a useful site to test out HTML, CSS, and Javascript snippets.
Backtick & String
const embeddedExpression = `Current Year: ${new Date().getFullYear()}`;- Use backticks
`in order to create a template literal string - string in Javascript that spans multiple lines and uses embedded expression ( i.e. ${variableName} )
Comments
// This line is a comment
/*
This block is also a comment
*/Console Log
console.log>("message");
try{
// do something
} catch (e) {
console.error>("Do something failed: ", e.message)
} finally {
console.log("Do something finished!")
}Variables
const: declare constant; can&pos;t be reassignlet: declare declare block-scoped variablesvar: avoid in modern code; delcare function-scoped variables (accessible even behondifandforloops statements)${variableName}: allow for clean injecting of Javascript variables/ expressions into the middle of string without having tovariableName + 'string literal'- Only usuable in a String
Variable Types
string: &pos;hello&pos;number: 5boolean: trueobject: { key: value }, [1, 2, 3], /regex/, new Date()function: function () , class MyClassbigint: 9007199254740992MAX_SAFE_NUMBER= 9007199254740991symbol:Symbol(x)undefined: a variable that has not been assigned a value
Unconventional Cases
// Numbers
typeof NaN === "number"; // Despite being "Not-A-Number"
typeof Number("shoe") === "number"; // Number tries to parse things into numbers
// Strings
typeof typeof 1 === "string"; // typeof always returns a string
typeof String(1) === "string"; // String converts anything into a string, safer than toString
// Booleans
typeof Boolean(1) === "boolean"; // Boolean() will convert values based on if they're truthy or falsy
typeof !!1 === "boolean"; // two calls of the ! (logical NOT) operator are equivalent to Boolean()
// Objects
typeof null === "object"; // null is also treated as false and 0;
// Avoid
typeof new Boolean(true) === "object";
typeof new Number(1) === "object";
typeof new String("abc") === "object";Notes
typeofcan be used to identify typeinstanceofcan be used to check if object is sublcass of anotherinstanceof Array: check if something is an array
Data Structures
| Feature | Array | Object | Set | Map |
|---|---|---|---|---|
| Type of keys: | Numeric indexes (0,1,2...) | Strings or Symbols | Values only (no keys) | Any value (objects, functions, primitives) |
| Allows duplicate values: | Yes | N/A (keys must be unique) | No (all values are unique) | Keys unique, values can duplicate |
| Order guaranteed: | Yes (insertion order) | No (property order is mostly insertion-based but not reliable for all cases) | Yes (insertion order) | Yes (insertion order) |
| Iteration support: | for, for...of, forEach, map, filter, reduce | for...in, Object.keys/values/entries | for...of, forEach | for...of, forEach |
| Primary use case: | Ordered list of values | Key-value pairs, fast property lookup | Unique values collection | Key-value pairs with any key type |
| Performance for lookups: | O(1) by index | O(1) by key (hash map under the hood) | O(1) for presence checks | O(1) for presence checks |
| Common methods: | push, pop, map, filter, reduce | Object.keys, Object.values, hasOwnProperty | add, delete, has, clear | set, get, has, delete, clear |
Notes
Arrayis best for ordered lists and sequential data.Objectis the traditional key-value structure, but keys are limited to strings/symbols.Setensures uniqueness, useful for deduplication.Mapis more flexible than objects since keys can be any type.
Operators
%: modulo (remainder)**: exponentiation++: increment--: decrement==: equality (type conversion allowed)===: strict equality (no type conversion)!=: inequality!==: strict inequality&&: logical AND||: logical OR??: nullish coalescing (returns right side only if left is null/undefined)
Conditionals
const value = 5;
// if / else
if (value > 3) {
console.log("Greater than 3");
} else {
console.log("Less than or equal to 3");
}
// ternary operator
const result = value > 3 ? "Big" : "Small";
console.log(result);
// switch statement
switch (value) {
case 1:
console.log("One");
break;
case 5:
console.log("Five");
break;
default:
console.log("Unknown");
}Truthy & Falsy
| Value / Example | Type | Boolean Result | Notes |
|---|---|---|---|
0, -0 | Number | Falsy | Zero values are falsy. |
0n | BigInt | Falsy | BigInt zero is falsy. |
NaN | Number | Falsy | Result of invalid numeric ops. |
"" | String | Falsy | Empty string only. |
null | Null | Falsy | Intentional “no value”. |
undefined | Undefined | Falsy | Uninitialized / missing value. |
Non-zero numbers (e.g., 1, -1, Infinity) | Number | Truthy | All non-zero numbers are truthy. |
Non-empty strings (e.g., "0", "false", " ") | String | Truthy | Even "0" and "false" are truthy. |
{} | Object | Truthy | Empty object is truthy. |
[] | Array | Truthy | Empty array is truthy. |
function() | Function | Truthy | All functions are truthy. |
Symbol() | Symbol | Truthy | All symbols are truthy. |
Non-zero BigInt (e.g., 1n, -5n) | BigInt | Truthy | Any BigInt except 0n. |
Objects like new Date(), new Map(), new Set() | Object | Truthy | Empty Map/Set are still truthy. |
Loops
// for loop
for (let i = 0; i < 5; i++) {
console.log(i);
}
// while loop
let count = 0;
while (count < 3) {
console.log(count);
count++;
}
// do...while loop
let j = 0;
do {
console.log(j);
j++;
} while (j < 3);
// for...of loop (arrays)
const arr = [1, 2, 3];
for (const num of arr) {
console.log(num);
}
// for...in loop (objects)
const obj = { a: 1, b: 2 };
for (const key in obj) {
console.log(key, obj[key]);
}Classes
Same as Java classes
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a sound`);
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} barks`);
}
}
const dog = new Dog("Rex");
dog.speak(); // Rex barksImporting
An alias can be used to replace really long names by using as (i.e.import {reallyLongName as newName} from 'script.js' )
- Named Import: import any exported Javascript bindings (i.e. functions, variables/constants, classes, objects)
//In script2.js
import {myFunction, MyClass} from "script1.js";>
myFunction();
const v = new MyClass();
------------------------------------------------
//In script1.js
export function myFunction{}
export class MyClass{}- Only one default can exist in each Javascript file
- Any new alias can be given to the default
//In script2.js
import NewNameClass from "script1.js";>
const v = new NewNameClass();
------------------------------------------------
//In script1.js
export default class MyClass{}//In script2.js
import * as myModule from "script1.js";>
myModule.myFunction();
const v = new myModule.NewNameClass();
------------------------------------------------
//In script1.js
export function myFunction{}
export class MyClass{}//In script2.js
import "script1.js";>
//myFunction is being run from the script2.js
------------------------------------------------
//In script1.js
export function myFunction{}
myFunction();Importing into HTML
The section in HTML Basics covered it.
Destructuring Syntax
Destructuring syntax can be used on arrays and objects to simplify code by using shorthand to unpack values into distinct variables
- The values of an array can be unpacked into an array of distinct variables; likewise, the properties of an object can be unpacked into an object with the same number of dinstinct variables
- When destructuring an array, the order of the distinct variables matter
- When destructuring an object, only the name of the properties matter and not the order, but requires parenthesis around the whole statement
- It's useful for destructuring function arguments
// JS
// Destructuring array (order matter)
const array = [1, 2, 3, 4, 5];
let first, second, rest;
[first, second, ...rest] = array;
// first = 1, second = 2, rest = [3, 4, 5]
------------------------------------------------
// Destructuring object (order does not matter, but need () )
const obj = {
prop1: 1,
prop2: 2,
prop3: 3,
prop4: {
a:10,
b:11,
c:12
}
};
let prop1, prop2, prop3, prop4, rest, a;
( {prop1, prop2, ...rest} = obj ); // parenthesis around the whole statement to tell JS it's an object literal
// prop1 = 1, prop2 = 2, rest = { prop3: 3, prop4: { a:10, b:11, c:12} }
( {prop3, prop4:{a} } = obj );
// prop3 = 3, prop4 = undefined, a = 10
------------------------------------------------
// Destructuring works well with function arguments
function myFunction(props) {
const prop1 = props.prop1;
...
}
function myFunction( {prop1} ){
...
}Computed Property Name
Normally, the keys of an object are literal, i.e. const obj = &123;key: 1 &125;; would have key itself as the key, but Computed Property Name allow Javascript to dynamically assign keys to object by replacing them with Javascript expressions.
- In order to use the value of a variable or expression as an object's key, add brackets
[]around it const obj = &123;[expression]: value &125;;- This syntax can only be used on objects' keys
- Useful in creating React forms or merging objects dynamically or when keys are not known until runtime
// JS
// Use for merging objects dynamically (i.e. updating an object field)
const field = "email";
const value = "alice@example.com";
const user = {name: "Alice", email: "old@example.com" };
// Create a new object with updated field dynamically
const updatedUser = {
...user,
[field]: value
};
console.log(updatedUser);
// {name: 'Alice', email: 'alice@example.com' }// JS
// Use for building API payloads based on user input
const params = ["sortBy", "filter"];
const values = ["date", "active"];
const payload = {
[params[0]]: values[0],
[params[1]]: values[1],
};
console.log(payload);
// {sortBy: 'date', filter: 'active' }// JS
// Computed keys with expressions
const i = 1;
const obj = {
["item_" + i]: "apple",
["item_" + (i + 1)]: "banana"
};
console.log(obj);
// {item_1: 'apple', item_2: 'banana' }Function Factory
funFactory(row) => () => {return(row)}
funFactorywill return a function() => {return(row)}that always return the value ofrow- If
rowwas an object, the reference will be saved by the factory; a copy or clone is needed to save the object's values - Can be useful for creating handlers to functions, configurating their parameters, and memoization
// Creating event handlers or callbacks
function clickLoggerFactory(message) {
return () => console.log(`Clicked: ${message}`);
}
button1.onclick = clickLoggerFactory("button1");
button2.onclick = clickLoggerFactory("button2");
------------------------------------------------------------
// Configurating function parameters
function apiCallerFactory(apiUrl) {
return async (endpoint) => {
const res = await fetch(`${apiUrl}/${endpoint}`);
return res.json();
};
}
const githubAPI = apiCallerFactory("https://api.github.com");
githubAPI("users/octocat").then(console.log);
------------------------------------------------------------
// Memoization
function memoAddFactory() {
const cache = {};
return (a, b) => {
const key = `${a},${b}`;
if (!(key in cache)) cache[key] = a + b;
return cache[key];
};
}
const addMemo = memoAddFactory();
console.log(addMemo(2, 3)); // 5
console.log(addMemo(2, 3)); // cached result: 5