Historical Context & Motivation
Before classes arrived in JavaScript, developers had to rely on functions and a feature called prototypes to create objects with shared behaviors. While this worked, the syntax was confusing and error-prone, especially for beginners. Other programming languages like Java, Python, and C++ had long used the class keyword to define blueprints for objects, and JavaScript developers wanted a cleaner way to do the same thing.
The need for organized, reusable code grew as web applications became more complex. Simple scripts that changed button colors evolved into full-scale apps like Gmail and Google Maps. Developers needed a structured approach to manage thousands of lines of code, and object-oriented programming (OOP) provided exactly that — a way to model real-world things as objects in code.
So the central question is this: how do you create a reusable template that lets you stamp out multiple objects, each with its own data but sharing the same behaviors? That is exactly what defining a class with a constructor and methods solves.
Core Principles & Definitions
A class is a blueprint or template that defines the structure and behavior of objects. Think of it like a cookie cutter: the cutter itself is the class, and each cookie you press out is an instance (an individual object created from that class). Every instance shares the same shape (properties and methods), but can hold different data.
Class Declaration
class keyword followed by a name (capitalized by convention). The body is wrapped in curly braces { }.Constructor Method
constructor() is a special method that runs automatically when you create a new instance with new. It sets up the initial properties of the object.The 'this' Keyword
this refers to the specific instance being created or acted upon. It lets each object store its own unique data.Methods
function keyword). They define behaviors that every instance can perform.Instantiation
new keyword followed by the class name and any arguments.enroll() or getSchedule().Visual Explanation — Anatomy of a Class
new Player() and holding its own unique data.Notice how the class definition on the left acts as a single source of truth. The constructor receives name and score as parameters and assigns them to this.name and this.score. Each instance on the right has its own copy of those property values, yet all three share the same greet() and addPoints() methods. This is the power of classes: write the behavior once and reuse it across as many objects as you need.
How It Works — Syntax Deep Dive
Declaring a Class
A class declaration starts with the class keyword, followed by the class name in PascalCase (each word capitalized, like ShoppingCart or UserProfile). The entire class body lives inside curly braces. Unlike regular objects, you do not use commas to separate methods.
ClassName — the name of your blueprint (PascalCase). constructor — a special method that initializes properties. methodName — any additional behavior the instances can perform.The Constructor in Detail
The constructor() method is called automatically every time you write new ClassName(). You can think of it as the "setup" step. Inside the constructor, you use this to attach properties to the new object. A class can have at most one constructor. If you don't write one, JavaScript provides an empty one automatically.
new keyword creates a fresh object, runs the constructor with the given arguments, and returns the finished instance.Defining Methods
Methods are functions that live inside the class body. You write them just like functions, but without the function keyword. They can accept parameters, perform logic, and access the instance's properties through this. Methods are shared across all instances — JavaScript stores one copy of each method and lets every object reference it, which is memory-efficient.
greet() { }, addPoints() { } with a comma will throw a syntax error.Detailed Breakdown — Class Execution Flow
Understanding the order in which things happen when you use a class is crucial for debugging. Let's trace through what happens step by step when you write const dog = new Pet("Buddy", "golden retriever");.
new keyword. Step 1 creates an empty object. Step 2 calls the constructor. Step 3 assigns properties via this. Step 4 links the methods. Step 5 returns the finished object.This process happens behind the scenes every single time you write new. Understanding this flow helps you see why forgetting the new keyword is a common bug — without it, JavaScript doesn't create the empty object in step 1, and this won't point to a fresh instance.
Worked Example — Building a BankAccount Class
Let's build a practical class from scratch. We'll create a BankAccount class that stores an owner's name and balance, and provides methods to deposit money, withdraw money, and check the balance.
class keyword and a descriptive PascalCase name. Open the curly braces for the class body.class BankAccount { }owner and balance parameters. Use this to store them as properties. We default the balance to 0 if none is provided.constructor(owner, balance = 0) { this.owner = owner; this.balance = balance; }amount parameter, adds it to this.balance, and returns the new balance. Notice there is no comma after the constructor — methods are simply listed one after another.deposit(amount) { this.balance += amount; return this.balance; }withdraw(amount) { if (amount > this.balance) { return "Insufficient funds"; } this.balance -= amount; return this.balance; }new and call their methods. Each instance tracks its own balance independently.const acct1 = new BankAccount("Maya", 500); acct1.deposit(200); // returns 700. const acct2 = new BankAccount("Leo"); acct2.deposit(50); // returns 50. acct2.withdraw(100); // returns "Insufficient funds"balance = 0 in the constructor. This is a default parameter — if no second argument is provided when creating an instance, balance automatically starts at 0. This is a handy JavaScript feature that works in any function, not just constructors.Classes vs. Other Approaches
Before ES6 classes, JavaScript developers used other patterns to create objects with shared behavior. Understanding these alternatives helps you appreciate what classes simplify, and helps you read older code you might encounter online.
| Feature | Object Literal | Constructor Function (old) | ES6 Class (modern) |
|---|---|---|---|
| Syntax | const obj = { } | function Dog() { } | class Dog { } |
| Reusable blueprint? | No — creates one-off objects | Yes, with new keyword | Yes, with new keyword |
| Method sharing | Methods duplicated per object | Via .prototype manually | Automatic via class body |
| Readability | Simple for small objects | Can be confusing | Clean and intuitive |
| Inheritance | Not straightforward | Possible but verbose | Easy with extends keyword |
Connection to Advanced OOP Concepts
Once you're comfortable defining classes with constructors and methods, you'll be ready to explore more advanced OOP features. These build directly on the foundation you've learned in this lesson, so understanding classes well now will make these next topics much more approachable.
| What You Learned | What Comes Next | Why It Matters |
|---|---|---|
| Defining a single class | Inheritance with extends | Create specialized classes that reuse a parent class's logic |
| Instance methods | Static methods with static | Methods that belong to the class itself, not to any instance |
| Public properties | Private fields with # | Protect data from being accessed or changed outside the class |
| Basic methods | Getters and setters | Computed properties that look like regular data access but run logic behind the scenes |
These advanced features all rely on the class structure you've just learned. For example, inheritance lets you write something like class SavingsAccount extends BankAccount — the child class automatically inherits the constructor and methods of the parent. This is only possible because the parent is defined as a proper class first. By mastering the basics now, you're setting yourself up to build complex, real-world applications.
Practice Problems
Book with a constructor that accepts title and author parameters, and a method called describe() that returns a string like "'The Great Gatsby' by F. Scott Fitzgerald".Counter that starts at 0 by default. It should have three methods: increment() (adds 1), decrement() (subtracts 1 but never goes below 0), and getCount() (returns the current count). Show the class definition and demonstrate creating an instance.QuizQuestion class. The constructor should accept questionText, choices (an array of strings), and correctIndex (the index of the correct answer). Add a method checkAnswer(index) that returns true or false, and a method getCorrectAnswer() that returns the correct choice text.class rectangle { Constructor(w, h) { width = w; height = h; }, area() { return w * h; } } const r = rectangle(5, 3);Lesson Summary
A class is a reusable blueprint for creating objects in JavaScript. You declare one with the class keyword and a PascalCase name. Inside the class body, the constructor method runs automatically when you use new and sets up each instance's unique properties using the this keyword. Methods are functions defined directly inside the class body (without the function keyword or commas between them) that define behaviors shared by all instances.
When you call new ClassName(args), JavaScript creates an empty object, runs the constructor to populate its properties, links the methods, and returns the finished instance. Each instance holds its own data but shares the same methods, making classes a powerful tool for writing organized, DRY (Don't Repeat Yourself) code. This foundation prepares you for advanced topics like inheritance, static methods, and private fields.