LearningJavaScript TutorialClasses & OOP
CHAPTER 14 · OBJECT-ORIENTED JAVASCRIPT

JavaScript Classes & OOP

Classes related data aur behavior ko reusable blueprints me organize karne ka modern syntax deti hain. Is chapter me constructor, instances, methods, inheritance, private fields, static methods aur composition ko practical examples se samjhenge.

English + Hinglish48 min readPractice included

What is OOP?

Object-Oriented Programming is a way to organize software around objects that combine state and behavior. JavaScript is multi-paradigm, so OOP is one useful tool — not the only way to write good JavaScript.

Hinglish Explanation

OOP me related data aur functions ko ek object ke around organize kiya jata hai. Jaise Student object ke paas name, score data ho aur getResult() behavior ho.

Class syntax

A class is a blueprint for creating similar objects.

class.jsJS
class Student {
  constructor(name, score) {
    this.name = name;
    this.score = score;
  }
}

const aman = new Student("Aman", 88);
console.log(aman);

The new keyword creates an instance and runs the class constructor.

constructor()

The constructor initializes each new instance. A class can have only one constructor method.

constructor.jsJS
class Course {
  constructor(title, level = "Beginner") {
    this.title = title;
    this.level = level;
  }
}

const js = new Course("JavaScript");
Remember: Constructor automatically runs with new Course(...); normally you do not call it directly.

Instances

Every object created with new is an instance of that class.

instances.jsJS
const html = new Course("HTML");
const css = new Course("CSS", "Intermediate");

console.log(html instanceof Course); // true
console.log(css.title);

Instance methods

Methods describe behavior shared by instances.

methods.jsJS
class Student {
  constructor(name, score) {
    this.name = name;
    this.score = score;
  }

  getResult() {
    return this.score >= 40 ? "Pass" : "Fail";
  }
}

const riya = new Student("Riya", 92);
console.log(riya.getResult());

Class methods live on the prototype and are shared rather than copied as a new function for every instance.

this inside classes

Inside a normal class method, this refers to the instance when the method is called through that instance.

this.jsJS
class Learner {
  constructor(name) {
    this.name = name;
  }

  greet() {
    return `Hello ${this.name}`;
  }
}
Method reference caution: If a method is detached from its object and called separately, its this context may be lost. Event handlers often need deliberate binding or wrapper functions.

Public class fields

Fields can declare per-instance properties directly in the class body.

fields.jsJS
class Student {
  isActive = true;

  constructor(name) {
    this.name = name;
  }
}

const student = new Student("Neha");
console.log(student.isActive);

Private fields

Names beginning with # are private to the class body.

private.jsJS
class Wallet {
  #balance = 0;

  deposit(amount) {
    if (amount > 0) this.#balance += amount;
  }

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

Code outside the class cannot access wallet.#balance directly.

Getters and setters

Getter and setter syntax can expose computed or controlled property access.

accessors.jsJS
class Student {
  constructor(name, score) {
    this.name = name;
    this._score = score;
  }

  get score() {
    return this._score;
  }

  set score(value) {
    if (value >= 0 && value <= 100) {
      this._score = value;
    }
  }
}
Do not overuse: Simple public properties are fine when no validation or computed behavior is required.

Static methods and fields

static members belong to the class itself, not to each instance.

static.jsJS
class ScoreUtils {
  static passingScore = 40;

  static isPass(score) {
    return score >= ScoreUtils.passingScore;
  }
}

console.log(ScoreUtils.isPass(75));

Inheritance with extends

A subclass can extend another class and inherit its methods.

inheritance.jsJS
class User {
  constructor(name) {
    this.name = name;
  }

  describe() {
    return `User: ${this.name}`;
  }
}

class Student extends User {
  constructor(name, course) {
    super(name);
    this.course = course;
  }
}

const learner = new Student("Aman", "JavaScript");

super()

In a derived class constructor, super() calls the parent constructor. You must call it before using this.

Important: In a subclass constructor, using this before super() causes an error.

Method overriding

A subclass can define a method with the same name to replace or extend parent behavior.

override.jsJS
class Student extends User {
  describe() {
    return `${super.describe()} · Student account`;
  }
}

Classes and prototypes

JavaScript classes are built on the language's prototype system. Class syntax makes constructor/prototype patterns easier to read, but it does not create a completely separate object model.

Simple idea

class ek clean syntax hai, lekin JavaScript ke andar inheritance aur shared methods prototypes ke through hi work karte hain.

Encapsulation

Encapsulation means keeping internal details behind a clear public interface. Private fields, small methods and validation boundaries can help.

encapsulation.jsJS
class ProgressTracker {
  #progress = 0;

  update(value) {
    this.#progress = Math.max(0, Math.min(100, value));
  }

  read() {
    return this.#progress;
  }
}

Composition over inheritance

Inheritance is useful for a real “is-a” relationship, but many applications are simpler when objects are built by combining smaller responsibilities.

composition.jsJS
const logger = {
  log(message) {
    console.log(`[LOG] ${message}`);
  }
};

class Course {
  constructor(title, loggerService) {
    this.title = title;
    this.logger = loggerService;
  }

  publish() {
    this.logger.log(`${this.title} published`);
  }
}

const course = new Course("JavaScript", logger);
Design rule: Deep inheritance trees are often harder to change. Prefer the simplest structure that clearly models the problem.

Four OOP ideas

  • Encapsulation: internal details ko controlled interface ke behind rakhna.
  • Abstraction: unnecessary implementation details hide karke useful operations expose karna.
  • Inheritance: parent behavior ko subclass me reuse/extend karna.
  • Polymorphism: same method name different object types me different behavior provide kar sakta hai.

When should you use classes?

Classes useful hain when you create many similar stateful objects with shared behavior, or when a domain naturally contains entities such as users, courses, carts or game characters.

Simple data transformation, one-off utility functions, DOM helpers or small modules ke liye plain functions and objects may be clearer.

Common beginner mistakes

  • new ke bina class call karna.
  • Subclass constructor me super() se pehle this use karna.
  • Static method ko instance method samajhna.
  • Every object ko class me convert kar dena.
  • Deep inheritance trees banana where composition is simpler.
  • Private #field ko outside access karne ki koshish karna.
  • Detached method me this automatically preserved samajhna.
  • Getter/setter ko simple property ke liye unnecessary complexity banana.
  • Class ko data validation/security boundary ka substitute samajhna.

Beginner best practices

  • Class name PascalCase me rakho: StudentProfile.
  • Constructor ko focused rakho; heavy work ko separate methods me move karo.
  • Methods ko one clear responsibility do.
  • Private fields only when real encapsulation benefit ho.
  • Inheritance only for clear is-a relationships.
  • Composition ko prefer karo when reusable capabilities combine karni hon.
  • Static members ko class-level behavior/data ke liye use karo.
  • Classes ko modules ke through small responsibilities me organize karo.

Chapter checklist

  • Class aur instance ka difference clear hai?
  • constructor() aur new use kar sakte ho?
  • Instance methods aur this samajh aaye?
  • Public and private fields ka basic difference clear hai?
  • static member ka role samajh aaya?
  • extends aur super() use kar sakte ho?
  • Method overriding ka basic pattern clear hai?
  • Inheritance vs composition kab choose karna hai iska idea hai?

Practice Task — Course Enrollment Model

Classes use karke small learning-domain model banao.

  1. User class banao with name and email.
  2. describe() instance method add karo.
  3. Student ko User se extend karo.
  4. Student constructor me super() use karo.
  5. course and score properties add karo.
  6. getResult() method create karo.
  7. Score ke liye validation-based setter ya update method banao.
  8. Ek private #completedLessons field add karo.
  9. Lesson complete karne aur count read karne ke methods banao.
  10. Class-level passing score ke liye static field banao.
  11. describe() override karke parent method ko super.describe() se reuse karo.
  12. 2–3 student instances create karke methods test karo.
  13. instanceof se inheritance relationship check karo.
  14. Finally socho: kisi feature ko inheritance ke bajay composition se better model kiya ja sakta hai?