JavaScript Advanced Concepts
CMU422: Fundamentals of Web Design - Session 8
Birmingham Newman University
Lecturer: James Williams
Functions, objects, and modern JavaScript
3-hour session • 26 slides • 2 interactive tasks
Session Timeline:
10 min: Registration & waiting
20 min: Opening slides
45 min: Task 1
15 min: Break/Catch up
20 min: Secondary slides
45 min: Task 2
Remaining: Self-study
Learning Objectives
Master advanced function concepts
Understand object-oriented programming
Learn modern JavaScript features
Work with asynchronous programming
Apply functional programming concepts
Advanced Function Concepts
Functions are first-class citizens in JavaScript
// Function declaration
function greet(name) { return `Hello ${name}`; }
// Function expression
const greet = function(name) { return `Hello ${name}`; };
// Arrow function
const greet = (name) => `Hello ${name}`;
// Immediately Invoked Function Expression (IIFE)
(function() { console.log('IIFE'); })();
Multiple ways to define functions
Functions can be assigned to variables
Functions can be passed as arguments
Functions can return other functions
Higher-Order Functions
// Function that returns a function
function multiply(x) {
return function(y) {
return x * y;
};
}
const multiplyByTwo = multiply(2);
console.log(multiplyByTwo(5)); // 10
// Function that takes a function as argument
function processArray(arr, callback) {
return arr.map(callback);
}
const numbers = [1, 2, 3, 4];
const doubled = processArray(numbers, x => x * 2);
Functions that return functions
Functions that take functions as arguments
Enable functional programming patterns
Create reusable and composable code
Try It: Advanced JavaScript Concepts
Closures
Promises
Async/Await
Closure Demo
Create
Counter
Increment
Create
Wallet
Deposit
$10
Withdraw $5
Click buttons to see closures in
action!
Promise Demo
Start Async Task
Promise Chain
Promise.all()
Click buttons to see promises in
action!
Async/Await Demo
Async
Function
Error Handling
Parallel
Execution
Click buttons to see async/await
in action!
Current Concept:
Closures allow functions to access
variables from their outer scope even after the outer function
has returned.
Explore advanced JavaScript concepts with interactive examples!
Closures
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
// Private variables
function createWallet(initialBalance) {
let balance = initialBalance;
return {
getBalance: () => balance,
deposit: (amount) => { balance += amount; },
withdraw: (amount) => {
if (amount <= balance) {
balance -= amount;
return true;
}
return false;
}
};
}
Functions that remember their lexical scope
Access to variables from outer scope
Used for data privacy and state management
Common in modern JavaScript patterns
Object-Oriented Programming
// Constructor function
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.greet = function() {
return `Hello, I'm ${this.name}`;
};
const person = new Person('John', 30);
console.log(person.greet()); // "Hello, I'm John"
// ES6 Classes
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, I'm ${this.name}`;
}
}
Constructor functions and prototypes
ES6 class syntax (syntactic sugar)
Inheritance and polymorphism
Encapsulation and abstraction
Inheritance
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a sound`;
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
speak() {
return `${this.name} barks`;
}
fetch() {
return `${this.name} fetches the ball`;
}
}
const dog = new Dog('Buddy', 'Golden Retriever');
console.log(dog.speak()); // "Buddy barks"
Use extends
for inheritance
Call super()
in constructor
Override methods in child classes
Add new methods to child classes
Modern JavaScript Features
// Destructuring
const { name, age } = person;
const [first, second, ...rest] = array;
// Spread operator
const newArray = [...oldArray, newItem];
const newObject = { ...oldObject, newProperty: value };
// Template literals
const message = `Hello ${name}, you are ${age} years old`;
// Default parameters
function greet(name = 'Guest') {
return `Hello ${name}`;
}
// Rest parameters
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
Destructuring for cleaner code
Spread operator for copying and merging
Template literals for string interpolation
Default and rest parameters
Promises
// Creating a promise
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
const random = Math.random();
if (random > 0.5) {
resolve('Success!');
} else {
reject('Failed!');
}
}, 1000);
});
// Using promises
myPromise
.then(result => console.log(result))
.catch(error => console.error(error));
// Promise chaining
fetch('/api/data')
.then(response => response.json())
.then(data => processData(data))
.catch(error => handleError(error));
Handle asynchronous operations
Better than callbacks
Chain multiple operations
Error handling with catch
Async/Await
// Async function
async function fetchUserData(userId) {
try {
const response = await
fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error('User not found');
}
const userData = await response.json();
return userData;
} catch (error) {
console.error('Error fetching user:', error);
throw error;
}
}
// Using async function
async function displayUser(userId) {
const user = await fetchUserData(userId);
console.log(`User: ${user.name}`);
}
// Arrow function with async
const loadData = async () => {
const data = await fetch('/api/data');
return data.json();
};
Syntactic sugar over promises
Makes async code look synchronous
Better error handling with try/catch
Easier to read and understand
ES6 Modules
// math.js (exporting)
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export default class Calculator {
multiply(a, b) { return a * b; }
}
// app.js (importing)
import Calculator, { add, subtract } from './math.js';
const calc = new Calculator();
console.log(add(5, 3)); // 8
console.log(calc.multiply(4, 2)); // 8
// Dynamic imports
const module = await import('./dynamic-module.js');
Organize code into separate files
Export and import functionality
Default and named exports
Dynamic imports for code splitting
Functional Programming Concepts
// Pure functions
const add = (a, b) => a + b;
const multiply = (a, b) => a * b;
// Function composition
const compose = (...fns) => x =>
fns.reduceRight((acc, fn) => fn(acc), x);
const addOne = x => x + 1;
const double = x => x * 2;
const addOneAndDouble = compose(double, addOne);
console.log(addOneAndDouble(5)); // 12
// Immutability
const original = [1, 2, 3];
const doubled = original.map(x => x * 2);
// original is unchanged
Pure functions (no side effects)
Function composition
Immutability
Higher-order functions
Modern Array Methods
const numbers = [1, 2, 3, 4, 5];
// Map
const doubled = numbers.map(x => x * 2);
// [2, 4, 6, 8, 10]
// Filter
const evens = numbers.filter(x => x % 2 === 0);
// [2, 4]
// Reduce
const sum = numbers.reduce((acc, x) => acc + x, 0);
// 15
// Find
const firstEven = numbers.find(x => x % 2 === 0);
// 2
// Some
const hasEven = numbers.some(x => x % 2 === 0);
// true
// Every
const allPositive = numbers.every(x => x > 0);
// true
Functional programming approach
Chain multiple operations
More readable than loops
Immutable operations
Advanced Error Handling
// Custom error classes
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = 'ValidationError';
this.field = field;
}
}
// Error handling with async/await
async function processData(data) {
try {
if (!data) {
throw new ValidationError('Data is
required', 'data');
}
const result = await validateAndProcess(data);
return result;
} catch (error) {
if (error instanceof ValidationError) {
console.error(`Validation error in
${error.field}:`, error.message);
} else {
console.error('Unexpected error:',
error);
}
throw error;
}
}
Custom error classes
Error inheritance
Type checking with instanceof
Proper error propagation
Performance Optimization
Memoization for expensive calculations
Debouncing and throttling
Lazy loading and code splitting
Efficient DOM manipulation
Memory leak prevention
// Memoization
function memoize(fn) {
const cache = new Map();
return function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn.apply(this, args);
cache.set(key, result);
return result;
};
}
// Debouncing
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
Testing JavaScript Code
Unit testing with Jest or Mocha
Test-driven development (TDD)
Mocking and stubbing
Integration testing
Code coverage
// Example test with Jest
function add(a, b) {
return a + b;
}
// test.js
describe('add function', () => {
test('adds two positive numbers', () => {
expect(add(2, 3)).toBe(5);
});
test('adds negative numbers', () => {
expect(add(-1, -2)).toBe(-3);
});
test('handles zero', () => {
expect(add(0, 5)).toBe(5);
});
});
Advanced Debugging
Browser developer tools
Console methods (log, warn, error, table)
Breakpoints and step-through
Performance profiling
Memory leak detection
// Debugging techniques
console.log('Debug info:', { user, data });
console.table(arrayOfObjects);
console.trace('Function call stack');
// Performance measurement
console.time('operation');
// ... expensive operation
console.timeEnd('operation');
// Debugger statement
function complexFunction() {
let result = 0;
debugger; // Execution stops here
return result;
}
Task 1: Advanced JavaScript Library
Instructions:
Create a new JavaScript file called advanced-library.js
Build a utility library with:
Math utilities: Advanced mathematical functions
Array utilities: Custom array manipulation methods
Object utilities: Deep cloning, merging, validation
Async utilities: Promise helpers and async
operations
Use modern JavaScript features:
ES6 classes and modules
Arrow functions and destructuring
Promises and async/await
Higher-order functions
Implement proper error handling
Add JSDoc documentation
Create unit tests for your functions
Time: 45 minutes
This task will help you understand advanced JavaScript concepts and
patterns
Break Time
15 Minutes
Take a break, ask questions, or catch up on the previous task.
Next: Secondary slides and Task 2
Common Design Patterns
Singleton: Single instance pattern
Factory: Object creation pattern
Observer: Event handling pattern
Module: Encapsulation pattern
Decorator: Function enhancement pattern
// Singleton pattern
class Database {
constructor() {
if (Database.instance) {
return Database.instance;
}
Database.instance = this;
}
}
// Factory pattern
class UserFactory {
createUser(type, data) {
switch(type) {
case 'admin': return new
AdminUser(data);
case 'regular': return new
RegularUser(data);
}
}
}
Memory Management
Garbage collection
Memory leaks prevention
Event listener cleanup
Closure memory considerations
WeakMap and WeakSet usage
// Memory leak prevention
class EventManager {
constructor() {
this.listeners = new Map();
}
addListener(element, event, handler) {
element.addEventListener(event, handler);
this.listeners.set(element, { event, handler });
}
removeListener(element) {
const listener = this.listeners.get(element);
if (listener) {
element.removeEventListener(listener.event,
listener.handler);
this.listeners.delete(element);
}
}
cleanup() {
this.listeners.forEach((listener, element) => {
this.removeListener(element);
});
}
}
Security Best Practices
Input validation and sanitization
XSS prevention
CSRF protection
Secure coding practices
Content Security Policy (CSP)
// Input validation
function validateInput(input) {
if (typeof input !== 'string') {
throw new Error('Input must be a string');
}
return input.replace(/[<>]/g, ''); // Basic XSS prevention
}
// Secure object property access
const safeGet = (obj, path) => {
return path.split('.').reduce((current, key) => {
return current && current[key] !== undefined ?
current[key] : null;
}, obj);
};
Code Quality and Standards
ESLint for code linting
Prettier for code formatting
JSDoc for documentation
TypeScript for type safety
Code review practices
// JSDoc documentation
/**
* Calculates the factorial of a number
* @param {number} n - The number to calculate factorial for
* @returns {number} The factorial of n
* @throws {Error} If n is negative
*/
function factorial(n) {
if (n < 0) {
throw new Error('Factorial is not defined for
negative numbers');
}
if (n === 0 || n === 1) {
return 1;
}
return n * factorial(n - 1);
}
Task 2: Complete Web Application
Instructions:
Create a complete web application using all concepts learned
Build a task management app with:
Architecture: Modular design with ES6 modules
Data Management: Local storage with CRUD operations
UI Components: Reusable components using classes
Async Operations: Simulated API calls with promises
Event Handling: Advanced event delegation and
custom events
Implement advanced features:
Task filtering and sorting
Drag and drop functionality
Real-time search with debouncing
Data validation and error handling
Responsive design with modern CSS
Use design patterns (Factory, Observer, Module)
Add comprehensive error handling and logging
Include unit tests for core functionality
Time: 45 minutes
This task will help you understand full-stack JavaScript development
Common Advanced Issues
Scope issues: Check closure and context
Async problems: Promise rejection handling
Memory leaks: Event listener cleanup
Performance issues: Profiling and optimization
Module errors: Import/export syntax
Type errors: Runtime type checking
// Common debugging patterns
// Check if function is called
console.log('Function called with:', arguments);
// Check promise state
promise.then(result => {
console.log('Promise resolved:', result);
}).catch(error => {
console.error('Promise rejected:', error);
});
// Check object structure
console.log('Object keys:', Object.keys(obj));
console.log('Object values:', Object.values(obj));
Session Summary
Master advanced function concepts and closures
Understand object-oriented programming
Use modern JavaScript features effectively
Handle asynchronous operations properly
Apply functional programming concepts
Write maintainable and testable code
Next Session:
Web APIs and External Libraries - Working with third-party services