OOP Interview Prep
OOP Fundamentals

What is OOP?

The Paradigm That Changed How We Write Code

LinkedIn Hook

You've been writing OOP code for years. But can you answer this in an interview?

"What problem does OOP actually solve — and why did we need it in the first place?"

Most developers freeze. They say "classes and objects" and stop there. That's not an answer. That's a vocabulary list.

In this lesson, you'll learn what OOP really is, why it was invented, and how to explain the difference between procedural and OOP code in a way that makes interviewers nod.

Because here's the uncomfortable truth: you can use class syntax every day and still not understand the paradigm behind it.

Read the full lesson → [link]

#OOP #JavaScript #SoftwareEngineering #Programming #InterviewPrep


What is OOP? thumbnail


What You'll Learn

  • What OOP is and why it exists as a response to real software engineering problems
  • How procedural code differs from OOP code, with side-by-side examples
  • How real-world objects map to code classes and why that mapping matters in interviews
  • The four pillars of OOP at a glance (deep dives come in later lessons)

The Problem OOP Was Built to Solve

Before OOP, software was written procedurally. Functions and data lived separately. As programs grew, that separation created a mess that was hard to maintain, test, and extend. OOP emerged in the 1960s-70s, with Simula 67 being the first language to introduce the concept, precisely to tame that complexity.

Think about a bank account. Procedurally, you have a variable for the balance and separate functions like deposit(), withdraw(), and getBalance(). Nothing stops another part of the program from setting the balance directly to a negative number. There's no protection, no single source of truth, and no logical grouping.

OOP solves this by bundling the data (balance) and the behavior (deposit, withdraw) together inside one unit called an object. That bundling is the core idea. Everything else in OOP builds on top of it.


What Exactly is OOP?

OOP, Object-Oriented Programming, is a programming paradigm that organizes code around objects rather than functions and procedures. An object is a self-contained unit that combines state (data) and behavior (methods).

The paradigm rests on four pillars: Encapsulation, Abstraction, Inheritance, and Polymorphism. This lesson gives you the foundation. Each pillar gets its own deep-dive chapter later in the course.

JavaScript supports OOP through prototypes (its native mechanism) and through the class syntax introduced in ES6, which is syntactic sugar over prototypes. Java and TypeScript have more formal OOP support, including access modifiers and interfaces, which we'll use where JavaScript falls short.

What is OOP? visual 1


The Real-World Analogy That Makes It Click

Consider a car. A car has state: color, fuel level, current speed, gear. It also has behavior: accelerate, brake, refuel. You don't need to know how the fuel injection system works to press the accelerator. That internal complexity is hidden. You interact through a clean interface.

That's OOP. The car is the object. Its internal state is protected. The pedals and steering wheel are the public interface.

Now think about a dog. A dog has state (name, breed, hunger level) and behavior (eat, bark, fetch). A dog is not a car. They're different objects with different structures. But they share a concept: both are things in the world with state and behavior.

When you write software, you model these real-world things as classes. A class is the blueprint. An object is the actual instance created from that blueprint. You can create a hundred Dog objects from one Dog class, each with its own name and hunger level.


Procedural vs OOP — Side by Side

This comparison comes up in almost every OOP interview. Know it cold.

Procedural Approach

// Procedural: data and functions are separate
let bankAccountBalance = 1000;
let bankAccountOwner = "Alice";

function deposit(amount) {
  bankAccountBalance += amount;
}

function withdraw(amount) {
  if (amount > bankAccountBalance) {
    console.log("Insufficient funds");
    return;
  }
  bankAccountBalance -= amount;
}

function getBalance() {
  return bankAccountBalance;
}

// Nothing stops this — direct mutation from anywhere
bankAccountBalance = -99999; // Bug waiting to happen

deposit(500);
console.log(getBalance()); // Output: 400 (balance was manually broken)

The functions here are global. The data is exposed. Any part of the codebase can corrupt bankAccountBalance directly. As the codebase grows, this becomes nearly impossible to manage.

OOP Approach

// OOP: data and behavior live together inside the object
class BankAccount {
  #balance; // private field (ES2022 syntax)

  constructor(owner, initialBalance) {
    this.owner = owner;
    this.#balance = initialBalance;
  }

  deposit(amount) {
    if (amount <= 0) {
      throw new Error("Deposit amount must be positive");
    }
    this.#balance += amount;
    console.log(`Deposited ${amount}. New balance: ${this.#balance}`);
  }

  withdraw(amount) {
    if (amount > this.#balance) {
      console.log("Insufficient funds");
      return;
    }
    this.#balance -= amount;
    console.log(`Withdrew ${amount}. New balance: ${this.#balance}`);
  }

  getBalance() {
    return this.#balance;
  }
}

const aliceAccount = new BankAccount("Alice", 1000);

aliceAccount.deposit(500);    // Output: Deposited 500. New balance: 1500
aliceAccount.withdraw(200);   // Output: Withdrew 200. New balance: 1300
console.log(aliceAccount.getBalance()); // Output: 1300

// This now throws an error — the data is protected
// aliceAccount.#balance = -99999; // SyntaxError: Private field access

The balance is now protected inside the object. No outside code can corrupt it directly. The object controls its own state through defined methods. That's encapsulation at work, and it's one of the core benefits OOP delivers.


The Four Pillars at a Glance

[INTERNAL-LINK: the four pillars overview → Lesson 1.3: The 4 Pillars Overview]

You'll get full lessons on each pillar starting in Chapter 2. For now, know what each one means at a high level, because interviewers often ask for a quick summary.

Encapsulation bundles data and methods together and restricts direct access to internal state. The bank account example above demonstrates it.

Abstraction hides complex implementation details and exposes only what the user needs. You press a button on a TV remote. You don't manage the infrared signals.

Inheritance lets a child class acquire the properties and methods of a parent class. A SavingsAccount can inherit from BankAccount and add interest logic without rewriting everything.

Polymorphism means "many forms." A Dog and a Cat can both have a speak() method. Calling speak() on either gives different output, but the calling code doesn't need to know which type it's dealing with.

// Polymorphism preview — same method call, different behavior
class Dog {
  speak() {
    return "Woof";
  }
}

class Cat {
  speak() {
    return "Meow";
  }
}

const animals = [new Dog(), new Cat(), new Dog()];

animals.forEach(animal => {
  console.log(animal.speak());
});
// Output:
// Woof
// Meow
// Woof

What is OOP? visual 2


The Tricky Edge Case Interviewers Love

Here's a question that separates candidates who understand OOP from candidates who just know the syntax.

"Is JavaScript truly object-oriented?"

The honest answer is: it depends on how strict your definition is. JavaScript uses prototypal inheritance, not classical inheritance. Every object has a hidden [[Prototype]] link to another object. The class keyword introduced in ES6 is syntactic sugar. Under the hood, class still uses prototypes.

// What class syntax looks like
class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    return `${this.name} makes a sound`;
  }
}

// What JavaScript actually does under the hood
function AnimalOld(name) {
  this.name = name;
}
AnimalOld.prototype.speak = function() {
  return `${this.name} makes a sound`;
};

const a1 = new Animal("Cat");
const a2 = new AnimalOld("Cat");

console.log(a1.speak()); // Output: Cat makes a sound
console.log(a2.speak()); // Output: Cat makes a sound

// They produce the same result via different mechanisms
console.log(typeof Animal); // Output: function (not "class"!)

JavaScript also doesn't have native access modifiers (private, protected, public keywords) outside of the # private field syntax from ES2022. TypeScript adds these at compile time, but they disappear at runtime.

So if an interviewer asks whether JavaScript is OOP, say: "JavaScript supports OOP concepts and can be used in an OOP style, but it uses prototypal inheritance rather than classical inheritance. The class syntax is syntactic sugar. It's a multi-paradigm language, not a pure OOP language."

That answer shows depth. It shows you understand the mechanism, not just the surface.

[INTERNAL-LINK: prototypal vs classical inheritance → Lesson 4.1: Inheritance Basics]


When Should You Use OOP?

OOP isn't always the right tool. Knowing when to reach for it and when not to is itself an interview signal.

OOP works well when you're modeling real-world entities with state and behavior, when you need to build large codebases with many developers, when you need code reuse through inheritance or composition, and when you want to enforce consistent interfaces across multiple types.

OOP can be overkill for simple scripts, pure data transformation pipelines, or functional programming tasks where state mutation is the enemy. Many modern JavaScript and TypeScript codebases mix OOP and functional styles deliberately.

The short interview answer: "OOP is a good fit when your domain naturally maps to entities with state and behavior, and when the codebase is large enough that organization and reuse matter."


Common Mistakes

  • Confusing a class with an object. A class is a blueprint. An object is an instance created from it. You can have one Car class and a thousand Car objects in memory. This distinction trips up many junior candidates.

  • Thinking OOP is just about using the class keyword. You can write deeply OOP code without class using factory functions and closures. Conversely, you can use class while violating every OOP principle. The paradigm is about structure and intent, not syntax.

  • Saying "OOP is always better than procedural." It's not. Simple utilities, one-off scripts, and pure transformation functions often belong in procedural or functional style. Good engineers choose the right paradigm for the problem.


Interview Questions

Q: What are the four pillars of OOP? Encapsulation, Abstraction, Inheritance, and Polymorphism. Encapsulation bundles data and behavior together. Abstraction hides internal complexity. Inheritance lets classes reuse logic from parent classes. Polymorphism allows objects of different types to be treated through a shared interface with different behavior per type.

Q: What is the difference between a class and an object? A class is a blueprint or template that defines the structure and behavior a type of object will have. An object is a concrete instance created from that blueprint at runtime. One class can produce many independent objects, each with its own state.

Q: Why did OOP emerge as a paradigm? As software grew in complexity, procedural code became hard to maintain. Functions and data lived separately, with no protection against unwanted state changes. OOP solved this by grouping related data and behavior into objects, making code easier to reason about, test, and extend.

Q: Is JavaScript a true OOP language? Covered in the main content above. The key points: JavaScript is multi-paradigm, uses prototypal rather than classical inheritance, and class is syntactic sugar over prototype-based mechanics.

Q: Can you write OOP code without using the class keyword in JavaScript? Yes. Factory functions, closures, and Object.create() can all produce objects with encapsulated state and shared methods. The class keyword is a convenience, not a requirement. This question appears specifically in JavaScript-focused interviews to test understanding of prototypes.


Quick Reference — Cheat Sheet

PARADIGM COMPARISON
-----------------------------------------------------------
Feature            Procedural           OOP
-----------------------------------------------------------
Code organization  Functions + data     Objects (data + methods)
Data protection    None by default      Encapsulation
Code reuse         Function calls       Inheritance / Composition
Modeling fit       Algorithms, scripts  Entities with state
Main risk          Spaghetti state      Over-engineering
-----------------------------------------------------------

OOP CORE CONCEPTS
-----------------------------------------------------------
Class        Blueprint / template for objects
Object       Instance created from a class
State        Data stored inside an object (properties)
Behavior     Actions an object can perform (methods)
-----------------------------------------------------------

THE 4 PILLARS (one-liner each)
-----------------------------------------------------------
Encapsulation   Bundle data + behavior, hide internal state
Abstraction     Show what's needed, hide how it works
Inheritance     Child class reuses parent class logic
Polymorphism    Same interface, different behavior per type
-----------------------------------------------------------

JAVASCRIPT OOP NOTES
-----------------------------------------------------------
- Uses prototypal inheritance (not classical)
- `class` keyword = syntactic sugar over prototypes
- `typeof ClassName` returns "function", not "class"
- Private fields: use `#fieldName` (ES2022)
- No native `abstract` or `interface` keywords (use TypeScript)
-----------------------------------------------------------

Previous: Start of course Next: Lesson 1.2 →


This is Lesson 1.1 of the OOP Interview Prep Course — 8 chapters, 41 lessons.

On this page