JavaScript • Object-Oriented Programming (Intro)

Defining Classes — Define classes with constructor and methods

Learn how JavaScript classes let you create reusable blueprints for objects with shared structure and behavior.

JavaScript emblem with code brackets, braces, and a code file.
Inside this lesson 10 sections 5 questions 6 figures

SECTION 1

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.

1995 • JavaScript Is Born

Brendan Eich creates JavaScript in just 10 days at Netscape. Objects exist, but there is no class keyword — developers use constructor functions and prototypes.

2009 • ES5 Standardized

ECMAScript 5 adds strict mode and Object.create(), making prototype-based patterns slightly easier, but still without a class syntax.

2015 • ES6 Introduces Classes

ECMAScript 2015 (ES6) introduces the class keyword, constructor methods, and a clean syntax for defining methods — a game-changer for readable OOP in JavaScript.

2020+ • Classes Everywhere

Modern frameworks like React and Node.js use classes extensively. Private fields, static methods, and other features continue to expand what classes can do.

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.

SECTION 2

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.

1

Class Declaration

You define a class using the class keyword followed by a name (capitalized by convention). The body is wrapped in curly braces { }.
2

Constructor Method

The 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.
3

The 'this' Keyword

Inside a class, this refers to the specific instance being created or acted upon. It lets each object store its own unique data.
4

Methods

Methods are functions defined inside the class body (without the function keyword). They define behaviors that every instance can perform.
5

Instantiation

Creating an object from a class is called instantiation. You use the new keyword followed by the class name and any arguments.
✦

KEY TAKEAWAY

Think of a class like a registration form for a new student. The form itself is the class — it defines what information is needed (name, grade, student ID). Each time a new student fills it out, that completed form is an instance. The constructor is the act of filling in the blanks, and the methods are things the student can do, like enroll() or getSchedule().

SECTION 3

Visual Explanation — Anatomy of a Class

Anatomy of a JavaScript ClassCLASS: Playerclass Player {CONSTRUCTORconstructor(name, score) {this.name = name;this.score = score;}METHODgreet() {return `Hi, I'm ${this.name}`;}METHODaddPoints(pts) {this.score += pts;}}INSTANCES (objects)p1name: "Alice"score: 100new Player("Alice", 100)p2name: "Bob"score: 250new Player("Bob", 250)p3name: "Chloe"score: 75new Player("Chloe", 75)new
The left panel shows the class definition with its constructor (cyan border) and two methods (pink and amber borders). The right panel shows three separate instances, each created with 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.

SECTION 4

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.

CLASS DECLARATION PATTERN

classClassNameconstructor(params)...methodName(params)...class ClassName { constructor(params) { ... } methodName(params) { ... } }

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.

INSTANTIATION PATTERN

constmyObj=newClassName(arg1,arg2);const myObj = new ClassName(arg1, arg2);

The 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.

⚠

Common Mistake

Don't put commas between methods in a class body. Unlike object literals where you separate key-value pairs with commas, class methods stand on their own. Writing greet() { }, addPoints() { } with a comma will throw a syntax error.

SECTION 5

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");.

Execution Flow: new Pet("Buddy", "golden retriever")1The new keyword creates an empty object{ } → a blank object is born in memory2constructor() runs with your argumentsconstructor("Buddy", "golden retriever") is called3this attaches properties to the objectthis.name = "Buddy"; this.breed = "golden retriever";4Methods are linked via the prototypedog.speak() and dog.fetch() become accessible5The finished object is returned and stored in dog{ name: "Buddy", breed: "golden retriever" }
This flowchart shows the five steps that happen internally when you use the 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.

SECTION 6

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.

Creating a BankAccount Class

  1. 1

    Step 1 — Declare the Class

    Start with the class keyword and a descriptive PascalCase name. Open the curly braces for the class body.
    class BankAccount { }
  2. 2

    Step 2 — Write the Constructor

    Inside the class, add a constructor that takes 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; }
  3. 3

    Step 3 — Add a deposit() Method

    Define a method that takes an 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; }
  4. 4

    Step 4 — Add a withdraw() Method

    This method checks if the balance is sufficient before subtracting. If not, it returns a warning message instead of allowing the withdrawal. This demonstrates how methods can include logic and conditionals.
    withdraw(amount) { if (amount > this.balance) { return "Insufficient funds"; } this.balance -= amount; return this.balance; }
  5. 5

    Step 5 — Create Instances and Use Methods

    Now create two accounts using 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"
💡

Default Parameters

In Step 2, notice 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.

SECTION 7

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.

FeatureObject LiteralConstructor Function (old)ES6 Class (modern)
Syntaxconst obj = { }function Dog() { }class Dog { }
Reusable blueprint?No — creates one-off objectsYes, with new keywordYes, with new keyword
Method sharingMethods duplicated per objectVia .prototype manuallyAutomatic via class body
ReadabilitySimple for small objectsCan be confusingClean and intuitive
InheritanceNot straightforwardPossible but verboseEasy with extends keyword

Comparison of three JavaScript approaches for creating objects with shared behavior.

✦

KEY TAKEAWAY

ES6 classes don't add new powers to JavaScript — they're "syntactic sugar" over the existing prototype system. Think of it like a graphical calculator vs. a command-line calculator: both do the same math, but one is much easier to use. Classes give you a cleaner, more familiar way to organize your code, which means fewer bugs and easier collaboration.

SECTION 8

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 LearnedWhat Comes NextWhy It Matters
Defining a single classInheritance with extendsCreate specialized classes that reuse a parent class's logic
Instance methodsStatic methods with staticMethods that belong to the class itself, not to any instance
Public propertiesPrivate fields with #Protect data from being accessed or changed outside the class
Basic methodsGetters and settersComputed properties that look like regular data access but run logic behind the scenes

How today's lesson connects to upcoming OOP concepts.

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.

SECTION 9

Practice Problems

Question 1: CONCEPTUAL

Explain the difference between a class and an instance in your own words. Why can you create multiple instances from a single class?
Show answer
A class is a blueprint or template that defines what properties and methods an object should have, but it doesn't hold any specific data itself. An instance is an actual object created from that class using the new keyword, filled in with real data. You can create multiple instances because each one gets its own separate copy of the property values (stored in memory), while the methods are shared. It's like how a house blueprint can produce many houses — each one has the same floor plan but different paint colors and furniture.

Question 2: BASIC

Write a class called 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".
Show answer
Here is the solution: class Book { constructor(title, author) { this.title = title; this.author = author; } describe() { return `'${this.title}' by ${this.author}`; } }. The constructor uses this to store the title and author on the instance. The describe() method accesses those properties through this and returns a formatted string using a template literal.

Question 3: INTERMEDIATE

Create a class called 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.
Show answer
class Counter { constructor(start = 0) { this.count = start; } increment() { this.count += 1; } decrement() { if (this.count > 0) { this.count -= 1; } } getCount() { return this.count; } } The constructor uses a default parameter so new Counter() starts at 0. The decrement() method uses an if statement to prevent the count from going negative. After const c = new Counter(); c.increment(); c.increment(); c.decrement(); calling c.getCount() would return 1.

Question 4: APPLIED

You're building a simple quiz app. Design a 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.
Show answer
class QuizQuestion { constructor(questionText, choices, correctIndex) { this.questionText = questionText; this.choices = choices; this.correctIndex = correctIndex; } checkAnswer(index) { return index === this.correctIndex; } getCorrectAnswer() { return this.choices[this.correctIndex]; } } You could use it like: const q = new QuizQuestion("What is 2+2?", ["3","4","5"], 1); q.checkAnswer(1); // true. q.getCorrectAnswer(); // "4". The checkAnswer() method uses strict equality (===) to compare the user's answer index with the stored correct index.

Question 5: CRITICAL THINKING

A student writes the following code and gets an error. Identify all the mistakes, explain why each one causes a problem, and write the corrected version. class rectangle { Constructor(w, h) { width = w; height = h; }, area() { return w * h; } } const r = rectangle(5, 3);
Show answer
There are four mistakes. (1) The class name rectangle should be Rectangle (PascalCase convention). (2) Constructor must be lowercase constructor — JavaScript won't recognize it otherwise. (3) Inside the constructor, width = w is missing this. — it should be this.width = w. Without this, you'd be creating global variables. There's also a comma between methods, which is invalid syntax. (4) The area() method references w * h instead of this.width * this.height. Finally, rectangle(5, 3) is missing the new keyword. Corrected: class Rectangle { constructor(w, h) { this.width = w; this.height = h; } area() { return this.width * this.height; } } const r = new Rectangle(5, 3);

SUMMARY

Lesson Summary

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.

Varsity Tutors • JavaScript • Defining Classes — Define classes with constructor and methods