
jguerra[at}northeastern.edu | @duto_guerra
Slides:http://johnguerra.co/lectures/webDevelopment_fall2025/05_Javascript/
Class page:http://johnguerra.co/classes/webDevelopment_fall_2025/
Based on: MDN JavaScript Guide
// var - function scoped, hoisted
var name = "John";
var name = "Jane"; // OK
// let - block scoped
let age = 25;
// let age = 30; // Error!
// const - block scoped, immutable
const PI = 3.14159;
// PI = 3; // Error!
var: function scoped, can redeclarelet: block scoped, no redeclarationconst: block scoped, immutable bindingconst, then letnumber: 42, 3.14string: "Hello"boolean: true/falseundefined: undefinednull: nullsymbol: Symbol("id")bigint: 123nobject: {}, []function: function() {}// Automatic type conversion
"5" + 3 // "53" (string concat)
"5" - 3 // 2 (number subtraction)
"5" == 5 // true (loose equality)
"5" === 5 // false (strict equality)
// Falsy values
if (!0) console.log("0 is falsy");
if (!"") console.log("empty string is falsy");
if (!null) console.log("null is falsy");
if (!undefined) console.log("undefined is falsy");
// Hoisted - can call before definition
console.log(add(2, 3)); // 5
function add(a, b) {
return a + b;
}
// Not hoisted
// console.log(subtract(5, 2)); // Error!
const subtract = function(a, b) {
return a - b;
};
// Traditional function
const multiply = function(a, b) {
return a * b;
};
// Arrow function - concise
const multiply2 = (a, b) => a * b;
// Arrow function - with block
const divide = (a, b) => {
if (b === 0) throw new Error("Division by zero");
return a / b;
};
// Single parameter (parentheses optional)
const square = x => x * x;
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter1 = createCounter();
const counter2 = createCounter();
console.log(counter1()); // 1
console.log(counter1()); // 2
console.log(counter2()); // 1 (separate closure)
// Default parameters
function greet(name = "World") {
return `Hello, ${name}!`;
}
// Rest parameters
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
// Destructuring parameters
function printUser({name, age, email}) {
console.log(`${name} (${age}): ${email}`);
}
printUser({name: "John", age: 30, email: "john@example.com"});
const age = 18;
if (age >= 21) {
console.log("Can drink");
} else if (age >= 18) {
console.log("Can vote");
} else {
console.log("Too young");
}
// Ternary operator
const status = age >= 18 ? "adult" : "minor";
const day = "monday";
switch (day) {
case "monday":
case "tuesday":
console.log("Weekday");
break;
case "saturday":
case "sunday":
console.log("Weekend");
break;
default:
console.log("Unknown day");
}
function parseJSON(str) {
try {
const data = JSON.parse(str);
return { success: true, data };
} catch (error) {
console.error("Parse error:", error.message);
return { success: false, error: error.message };
} finally {
console.log("Parse attempt completed");
}
}
// Throwing custom errors
function divide(a, b) {
if (b === 0) {
throw new Error("Division by zero is not allowed");
}
return a / b;
}
for (let i = 0; i < 5; i++) {
console.log(i);
}
let i = 0;
while (i < 5) {
console.log(i);
i++;
}
let i = 0;
do {
console.log(i);
i++;
} while (i < 5);
for (let i = 0; i < 10; i++) {
if (i === 3) continue; // skip 3
if (i === 7) break; // stop at 7
console.log(i);
}
const obj = {a: 1, b: 2, c: 3};
for (const key in obj) {
console.log(key, obj[key]);
}
// Output: "a" 1, "b" 2, "c" 3
const arr = ["x", "y", "z"];
for (const index in arr) {
console.log(index); // "0", "1", "2"
}
const arr = ["x", "y", "z"];
for (const value of arr) {
console.log(value);
}
// Output: "x", "y", "z"
const str = "hello";
for (const char of str) {
console.log(char); // "h", "e", "l", "l", "o"
}
const person = {
name: "John",
age: 30,
greet() {
return `Hello, I'm ${this.name}`;
}
};
console.log(person.greet()); // Hello, I'm John
function Person(name, age) {
this.name = name;
this.age = age;
}
const john = new Person("John", 30);
const personProto = {
greet() {
return `Hello, I'm ${this.name}`;
}
};
const john = Object.create(personProto);
john.name = "John";
john.age = 30;
// Dot notation
person.name = "Jane";
// Bracket notation
person["age"] = 25;
// Dynamic properties
const prop = "email";
person[prop] = "jane@example.com";
class Animal {
constructor(name, species) {
this.name = name;
this.species = species;
}
speak() {
return `${this.name} makes a sound`;
}
static getKingdom() {
return "Animalia";
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name, "Canis lupus");
this.breed = breed;
}
speak() {
return `${this.name} barks`;
}
}
const dog = new Dog("Rex", "Golden Retriever");
console.log(dog.speak()); // Rex barks
class Circle {
constructor(radius) {
this._radius = radius;
}
get radius() {
return this._radius;
}
set radius(value) {
if (value < 0) {
throw new Error("Radius cannot be negative");
}
this._radius = value;
}
get area() {
return Math.PI * this._radius ** 2;
}
}
const circle = new Circle(5);
console.log(circle.area); // 78.54
const name = "John";
const age = 30;
// Old way
const message1 = "Hello, my name is " + name + " and I'm " + age + " years old.";
// Template literals (ES6+)
const message2 = `Hello, my name is ${name} and I'm ${age} years old.`;
// Multi-line strings
const html = `
${name}
Age: ${age}
`;
// Tagged templates
function highlight(strings, ...values) {
return strings.reduce((result, string, i) => {
return result + string + (values[i] ? `${values[i]}` : '');
}, '');
}
const highlighted = highlight`Name: ${name}, Age: ${age}`;
const arr = [1, 2, 3, 4, 5];
const [first, second, ...rest] = arr;
console.log(first); // 1
console.log(rest); // [3, 4, 5]
// Swapping variables
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a, b); // 2, 1
const user = {
name: "John",
age: 30,
email: "john@example.com"
};
const {name, age, email} = user;
// With aliases
const {name: userName, age: userAge} = user;
// With defaults
const {city = "Unknown"} = user;
// Arrays
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2];
// Objects
const obj1 = {a: 1, b: 2};
const obj2 = {c: 3, d: 4};
const merged = {...obj1, ...obj2};
// Function calls
const numbers = [1, 2, 3];
console.log(Math.max(...numbers));
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
// With other parameters
function greet(greeting, ...names) {
return `${greeting} ${names.join(", ")}`;
}
console.log(greet("Hello", "John", "Jane"));
function fetchUser(id) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (id > 0) {
resolve({id, name: `User ${id}`});
} else {
reject(new Error("Invalid ID"));
}
}, 1000);
});
}
fetchUser(1)
.then(user => console.log(user))
.catch(error => console.error(error));
async function getUser(id) {
try {
const user = await fetchUser(id);
console.log(user);
return user;
} catch (error) {
console.error(error);
throw error;
}
}
// Usage
getUser(1);
// Multiple async operations
async function getMultipleUsers() {
const users = await Promise.all([
fetchUser(1),
fetchUser(2),
fetchUser(3)
]);
return users;
}
// math.js
export function add(a, b) {
return a + b;
}
export const PI = 3.14159;
export default class Calculator {
multiply(a, b) {
return a * b;
}
}
// Alternative export syntax
function subtract(a, b) {
return a - b;
}
export { subtract };
// main.js
import Calculator, { add, PI } from './math.js';
const calc = new Calculator();
console.log(calc.multiply(2, 3)); // 6
console.log(add(4, 5)); // 9
console.log(PI); // 3.14159
// Import all
import * as math from './math.js';
console.log(math.add(1, 2));
// Dynamic imports
async function loadMath() {
const math = await import('./math.js');
return math.add(1, 2);
}
const numbers = [1, 2, 3, 4, 5];
// Transformation methods
const doubled = numbers.map(n => n * 2); // [2, 4, 6, 8, 10]
const filtered = numbers.filter(n => n > 3); // [4, 5]
const sum = numbers.reduce((acc, n) => acc + n, 0); // 15
// Find methods
const found = numbers.find(n => n > 3); // 4
const foundIndex = numbers.findIndex(n => n > 3); // 3
// Check methods
const hasEven = numbers.some(n => n % 2 === 0); // true
const allPositive = numbers.every(n => n > 0); // true
// Modification methods
numbers.push(6); // Add to end
numbers.unshift(0); // Add to beginning
numbers.splice(2, 1); // Remove 1 element at index 2
const uniqueNumbers = new Set([1, 2, 3, 3, 4]);
console.log(uniqueNumbers); // Set {1, 2, 3, 4}
uniqueNumbers.add(5);
uniqueNumbers.delete(1);
console.log(uniqueNumbers.has(2)); // true
console.log(uniqueNumbers.size); // 4
// Convert to array
const arr = [...uniqueNumbers];
const userRoles = new Map();
userRoles.set("john", "admin");
userRoles.set("jane", "user");
console.log(userRoles.get("john")); // "admin"
console.log(userRoles.has("bob")); // false
console.log(userRoles.size); // 2
// Iterate
for (const [user, role] of userRoles) {
console.log(`${user}: ${role}`);
}
const btn = document.querySelector("#btnExample");
const output = document.querySelector("#output");
let count = 0;
btn.addEventListener("click", () => {
count++;
output.innerHTML = `
Clicked ${count} time${count !== 1 ? 's' : ''}!
`;
});
// Modern way to make HTTP requests
async function fetchUsers() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const users = await response.json();
return users;
} catch (error) {
console.error('Failed to fetch users:', error);
throw error;
}
}
// Usage
fetchUsers()
.then(users => {
users.forEach(user => console.log(user.name));
})
.catch(error => console.error(error));
const by default, let when reassigning===) over loose (==)const userManager = (() => {
let users = [];
return {
addUser(user) {
users.push(user);
},
getUsers() {
return [...users];
},
getUserCount() {
return users.length;
}
};
})();
class EventEmitter {
constructor() {
this.events = {};
}
on(event, listener) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(listener);
}
emit(event, data) {
if (this.events[event]) {
this.events[event].forEach(listener =>
listener(data)
);
}
}
}
Build a listings page from the SF Airbnb listings for Sept 2023 JSON file.