JavaScript¶
JavaScript Characteristics¶
- Interpreted and just-in-time compiled (via the V8 Engine)
- Java-like syntax, but influenced by functional languages
- Early JavaScript syntax was functional, similar to Scheme (e.g., Racket)
- Prototype-based object-oriented language
- Dynamically typed (like Python)
- Not statically typed (like Java)
- Loosely/weakly typed
- Not strongly typed (like Python)
- e.g., "5" - 2 → coerces to 3
- Based on an evolving standard
- ECMAScript (e.g., ES6 and later)
- Supports:
- Strict mode (safer, stricter syntax)
- Non-strict mode ("sloppy mode")
- Vite and TypeScript default to strict mode such that
x = 10; // ❌ ReferenceError: x is not defined
Basics¶
- Semicolon line endings are optional
- But it's recommended to use them.
-
Console output (e.g., in a browser)
console.log(...) -
Control structures (similar to C/Java):
if (...) { ... } else { ... } for (...) { ... } while (...) { ... } switch (...) { ... } -
Ternary operator
A ? B : C // equivalent to "if A then B else C"
Variables and Types¶
-
Use
letandconstto declare variables.varis outdated (non-block scope, hoisting issues).-
Hoisting means JavaScript moves declarations to the top of their scope (function or global) during compilation — before any code runs.
- Only declarations are hoisted — not initializations.
console.log(x); // undefined var x = 5;Internally, JavaScript interprets this as:
var x; // hoisted declaration console.log(x); // undefined x = 5; // assignment stays in place
Note
🚫
WARNING
When you declare a variable with var inside a block ({}), it’s not scoped to that block — it’s scoped to the entire enclosing function (or global if outside a function).
function test() { if (true) { var x = 10; } console.log(x); // ✅ Outputs: 10 (because `var` is function-scoped) } -
Primitive types:
boolean,number,string,null,undefined- Everything else is an object (including arrays).
undefinedmeans the variable has been declared but not assigned.- JavaScript supports automatic type conversion.
- Use
typeofto check the type of a variable (returns a string).- Note:
typeofoften returns"object"even for arrays.
- Note:
Truthy and Falsy in JavaScript¶
JavaScript uses automatic type conversion, which can lead to surprising behavior with ==.
Examples with == (loose equality)
0 == "" // true!
1 == "1" // true!
These are true because of type coercion.
Prefer === (strict equality) to avoid unexpected results
0 === "" // false
1 === "1" // false
===checks both value and type, avoiding type coercion.
Logical OR and Nullish Coalescing¶
-
||is the logical OR operator-
Commonly used to assign a default if the variable is falsy
let v; v = v || 456; // v is 456 since v was undefined -
⚠️ May lead to bugs due to truthy/falsy behavior
let v = 0; v = v || 456; // v is 456 since 0 is falsy
-
-
??is the nullish coalescing operator-
Only uses default if the value is
nullorundefinedlet result = value ?? defaultValue;let v = 0; v = v ?? 456; // v is 0 since it's not null or undefined
-
Functions¶
- Function declaration
function add1(a, b) { return a + b; }
console.log(add1(1, 2)); // 3
- Function expression
const add2 = function (a, b) { return a + b; }
console.log(add2(1, 2)); // 3
- Arrow function expression (also called "lambda notation")
const add3 = (a, b) => a + b;
console.log(add3(1, 2)); // 3
First Class Functions¶
- Functions can be assigned to variables
function sayHello() { return "Hello, "; }
const saySomething = sayHello;
console.log(saySomething()); // "Hello, "
- Functions can be passed to other functions (e.g., callback functions)
- A callback function is a function that is passed as an argument to another function and is invoked (called) later during the execution of that function.
function greeting(msg, name) { return msg() + name; }
console.log(greeting(sayHello, "Sam")); // "Hello, Sam"
- Functions can be returned from other functions (e.g., factory functions)
function makeGreeting() {
return function (name) { return "Hi " + name; };
}
const greet = makeGreeting();
console.log(greet("Sam")); // "Hi Sam"
Closures¶
A closure occurs when an inner function retains access to the outer function’s state.
- Inner function referencing outer scope
function makeRandomGreeting() {
const sal = Math.random() > 0.5 ? "Hi" : "Hello";
return function (name) { return sal + " " + name; }
}
const greeting = makeRandomGreeting();
console.log(greeting("Sam")); // ?? Sam
- Closure with function parameter
function makeGreeting(sal) {
return function (name) { return sal + " " + name; }
}
const greeting1 = makeGreeting("Hello");
console.log(greeting1("Sam")); // Hello Sam
Passing Functions to Factory Functions¶
- Factory function that accepts another function as input:
function makeGreeting(msg) {
return function (name) { return msg() + name; }
}
function sayHello() { return "Hello, "; }
const greeting2 = makeGreeting(sayHello);
console.log(greeting2("Sam")); // Hello, Sam
- Using anonymous arrow function (lambda):
const greeting3 = makeGreeting(() => "Howdy! ");
console.log(greeting3("Sam")); // Howdy! Sam
String Template Literals¶
- String literals delimited by backticks ``` enable:
- String interpolation
- (Also supports multi-line strings and tagged templates, not covered here)
- Example
const v = 15.7;
const units = "cm";
- Without string interpolation:
let msg = "Length is " + v + " " + units + ".";
- With string interpolation:
let msg = `Length is ${v} ${units}.`;
- Using expressions in template literals:
let msg = `Length is ${((v / 100).toFixed(2) * 100)} cm.`;
JavaScript Objects¶
- JavaScript objects can be defined using JSON-like syntax:
const square = {
colour: "red",
size: 10,
draw: function () {
return `A ${this.size} pixel ${this.colour} square.`;
}
};
- Get a property:
console.log(square.colour); // red
- Set a property:
square.colour = "blue";
- Call a method (function property):
console.log(square.draw()); // A 10 pixel blue square.
Class (like a “template” for creating objects)¶
- The
classkeyword is syntactic sugar over JavaScript's prototypal inheritance.
class Shape {
constructor(colour) {
this.colour = colour;
}
draw() {
return `A ${this.colour} shape.`;
}
}
- Inheritance is done using
extends, andsuper()calls the parent constructor:
class Square extends Shape {
constructor(colour, size) {
super(colour); // Calls the Shape constructor
this.size = size;
}
draw() {
return `A ${this.colour} square size ${this.size}`;
}
}
- Create a new instance:
const square = new Square("red", 10);
Arrays¶
Arrays are an example of an iterable object.
- Declaring Arrays
let arr1 = []; // empty array with length 0
let arr2 = Array(5); // empty array with length 5
let arr3 = [1, 2, 3, 4, 5]; // populated array
let arr4 = Array(5).fill(99); // 5 elements, all 99
- Iterating Over Arrays
for (let i = 0; i < arr3.length; i++) {
console.log(arr3[i]);
}
for (const x of arr3) {
console.log(x);
}
arr3.forEach((x) => console.log(x));
Array Methods¶
foreachsortreversespliceindexOf- … many more
Note some mutate the array and some don't
Common Functional Array Methods¶
let arr3 = [1, 2, 3, 4, 5];
mapreturns array with transformed elements:
const arr4 = arr3.map((x) => x * 10);
// [10, 20, 30, 40, 50]
findreturns first element that satisfies condition:
const a = arr3.find((x) => x % 2 == 0);
// 2
filterreturns all elements that satisfy condition:
const arr5 = arr3.filter((x) => x % 2 == 0);
// [2, 4]
reduceexecutes a function that accumulates to a single return value:
const arr6 = arr3.reduce((acc, x) => acc + x, 0); // 0 is the initial value of acc
// 15
Destructuring Assignment¶
Unpack array elements or object properties into distinct variables
- From Arrays
let arr3 = [1, 2, 3, 4, 5];
let [a, b] = arr3; // a = 1, b = 2
- From Objects
let obj = { "a": 1, "b": 2, "c": 3 };
let { a, b } = obj; // a = 1, b = 2
- Renaming destructured variables from objects
let obj = { "a": 1, "b": 2, "c": 3 };
let { a: x, b: y } = obj; // x = 1, y = 2
b: y means "unpack value for b and store in y"
Spread Syntax and Rest Syntax¶
- Spread: expands an iterable object (like arrays or strings)
let arr3 = [1, 2, 3, 4, 5];
let arr4 = [-1, 0, ...arr3, 6, 7];
console.log(arr4); // [-1, 0, 1, 2, 3, 4, 5, 6, 7]
- Rest: condenses multiple elements into a single variable
let arr3 = [1, 2, 3, 4, 5];
let [a, b, ...c] = arr3;
console.log(c); // [3, 4, 5]
- Rest with objects
const obj = { a: 1, b: 2, c: 3 };
let { a, ...x } = obj;
console.log(x); // { b: 2, c: 3 }
let { b, ...y } = obj; // Extract the property named b from obj and store it in variable b.
// y is { a: 1, c: 3 }
Create a Prepopulated Array using spread and map¶
let arr5 = [...Array(5)].map((_, i) => i * 10);
// Breakdown:
// [...Array(5)] → creates an array with 5 undefined elements and spreads them into a new array
// .map((_, i) => i * 10) → maps each index to a value by multiplying it by 10
// _ is used to ignore the undefined value
console.log(arr5); // [0, 10, 20, 30, 40]
The index parameter i is optional in map