Module 3: Object References, Linked Lists and Classes

Module Overview

In this module, you'll dive deep into object references, linked lists, and classes. These concepts are fundamental to understanding data structures and object-oriented programming in JavaScript.

Module Objectives

  • Understand object references and how they differ from primitive values
  • Learn about memory management and object mutation in JavaScript
  • Implement linked list data structures using object references
  • Create and extend JavaScript classes for data structure implementations
  • Practice traversing, manipulating, and optimizing linked data structures
  • Apply object-oriented programming concepts to solve complex problems

Module Content

1. Object References

This video explores how objects are stored and referenced in JavaScript, which is fundamental to understanding more complex data structures.

Key Concepts:

  • Primitive vs. reference types in JavaScript
  • How objects are stored in memory
  • Understanding shallow vs. deep copying
  • Object mutation and its implications

Code Example:

// Primitive types are copied by value
let a = 5;
let b = a; // b gets a copy of the value
a = 10;    // Changing a doesn't affect b
console.log(b); // Still 5

// Objects are copied by reference
let obj1 = { name: 'Alice', age: 30 };
let obj2 = obj1; // obj2 references the same object as obj1
obj1.age = 31;   // Mutating obj1 also changes obj2
console.log(obj2.age); // 31

// Shallow copying
let original = { name: 'Bob', profile: { job: 'Developer' } };
let shallowCopy = { ...original }; // Spread operator creates a shallow copy

// Deep copying
let deepCopy = JSON.parse(JSON.stringify(original)); // Simple deep copy method
// But be careful, this doesn't work for functions, dates, etc.
                        

2. Linked Lists - Part 1: Concepts and Structure

This video introduces linked lists, explaining their structure, advantages, and use cases compared to arrays.

Key Concepts:

  • Basic structure of singly linked lists
  • Nodes and references
  • Head, tail, and traversal
  • Advantages and disadvantages compared to arrays

Code Example - Node Structure:

// Basic node structure for a singly linked list
class Node {
  constructor(value) {
    this.value = value;    // The data stored in this node
    this.next = null;      // Reference to the next node
  }
}

// Example of creating and linking nodes manually
const node1 = new Node(10);
const node2 = new Node(20);
const node3 = new Node(30);

// Link the nodes together
node1.next = node2;
node2.next = node3;

// Traverse the linked list
let current = node1;
while (current !== null) {
  console.log(current.value);
  current = current.next;
}
// Output: 10, 20, 30
                        

2. Linked Lists - Part 2: Implementation

In this video, you'll learn how to implement a linked list in JavaScript using classes, with various operations for manipulating the list.

Operations Covered:

  • Inserting nodes (at head, tail, or specific position)
  • Removing nodes
  • Searching for values
  • Traversing the list
  • Handling edge cases

Code Example - Linked List Implementation:

class LinkedList {
  constructor() {
    this.head = null;
    this.tail = null;
    this.length = 0;
  }
  
  // Add to the end of the list
  append(value) {
    const newNode = new Node(value);
    
    if (!this.head) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      this.tail.next = newNode;
      this.tail = newNode;
    }
    
    this.length++;
    return this;
  }
  
  // Add to the beginning of the list
  prepend(value) {
    const newNode = new Node(value);
    
    if (!this.head) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      newNode.next = this.head;
      this.head = newNode;
    }
    
    this.length++;
    return this;
  }
  
  // Find a node by its value
  find(value) {
    if (!this.head) return null;
    
    let current = this.head;
    while (current) {
      if (current.value === value) {
        return current;
      }
      current = current.next;
    }
    
    return null;
  }
}

// Usage example
const list = new LinkedList();
list.append(10).append(20).append(30);
console.log(list.find(20)); // Node with value 20
                        

3. Classes in JavaScript

This video explores the ES6 class syntax in JavaScript and how to use it for creating reusable object templates.

Key Concepts:

  • Class declarations and expressions
  • Constructor methods
  • Instance methods and properties
  • Static methods and properties
  • Inheritance with extends
  • super keyword

Code Example - Class Implementation:

// Basic class declaration
class Vehicle {
  constructor(make, model, year) {
    this.make = make;
    this.model = model;
    this.year = year;
    this.isRunning = false;
  }
  
  // Instance method
  start() {
    this.isRunning = true;
    return `The ${this.make} ${this.model} is now running.`;
  }
  
  stop() {
    this.isRunning = false;
    return `The ${this.make} ${this.model} is now stopped.`;
  }
  
  // Static method (called on the class itself, not instances)
  static isVehicle(obj) {
    return obj instanceof Vehicle;
  }
}

// Inheritance
class Car extends Vehicle {
  constructor(make, model, year, numDoors) {
    // Call parent constructor
    super(make, model, year);
    this.numDoors = numDoors;
  }
  
  // Override parent method
  start() {
    const message = super.start(); // Call parent method
    return `${message} All ${this.numDoors} doors are locked.`;
  }
}

// Usage
const myCar = new Car('Toyota', 'Camry', 2022, 4);
console.log(myCar.start());
// Output: "The Toyota Camry is now running. All 4 doors are locked."
                        

4. Implementing Data Structures with Classes

In this final video, you'll learn how to use classes to implement various data structures beyond linked lists.

Data Structures Covered:

  • Stacks
  • Queues
  • Binary Trees
  • Hash Tables

Code Example - Stack Implementation:

class Stack {
  constructor() {
    this.items = [];
  }
  
  // Add an element to the top of the stack
  push(element) {
    this.items.push(element);
  }
  
  // Remove and return the top element
  pop() {
    if (this.isEmpty()) {
      return "Underflow - Stack is empty";
    }
    return this.items.pop();
  }
  
  // Look at the top element without removing it
  peek() {
    if (this.isEmpty()) {
      return "Stack is empty";
    }
    return this.items[this.items.length - 1];
  }
  
  // Check if the stack is empty
  isEmpty() {
    return this.items.length === 0;
  }
  
  // Return the size of the stack
  size() {
    return this.items.length;
  }
  
  // Clear the stack
  clear() {
    this.items = [];
  }
}

// Usage example
const stack = new Stack();
stack.push(10);
stack.push(20);
stack.push(30);

console.log(stack.peek()); // 30
console.log(stack.pop());  // 30
console.log(stack.size()); // 2
                        

5. Guided Project

Complete the Module 3 Guided Project to practice implementing and working with linked lists and classes.

Project Focus:

  • Building a doubly linked list
  • Creating a class hierarchy for different data structures
  • Implementing advanced operations (sorting, reversing, etc.)
  • Testing and debugging your implementations

6. Practice Activities

  • Module 3 Practice Exercises
  • Check for Understanding Quiz
  • Practice GCA Test

Instead of using CodeSignal Arcade which is no longer available, we recommend the following LeetCode collections that focus on linked lists and object-oriented programming: