Skip to main content

Classes & Constructors

Introduction​

JavaScript is an object-oriented language, and one way to create objects is by using classes. A class is a blueprint for creating objects that share the same structure (properties) and behavior (methods).

When you create a new object from a class, the constructor method runs automatically. It sets up the object’s initial state.

Modern JavaScript also allows private fields (with a # prefix), which enforce encapsulation by preventing outside code from directly accessing sensitive data.


Concepts​

Declaring a Class

class Person {
constructor(name, age) {
this.name = name; // public property
this.age = age;
}
}

Creating Instances

const alice = new Person("Alice", 25);
console.log(alice.name); // "Alice"

Methods

class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hi, I'm ${this.name} and I'm ${this.age} years old.`;
}
}

Private Fields

class BankAccount {
#balance; // private

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

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

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

const acc = new BankAccount("Alice", 100);
acc.deposit(50);
console.log(acc.getBalance()); // 150
// acc.#balance ❌ Error: private field

Getters & Setters

Encapsulation allows controlled access with getters and setters.

class Employee {
#salary;

constructor(name, salary) {
this.name = name;
this.#salary = salary;
}

get salary() {
return this.#salary;
}

set salary(amount) {
if (amount < 0) throw new Error("Salary cannot be negative");
this.#salary = amount;
}
}

const emp = new Employee("Alice", 50000);
console.log(emp.salary); // 50000
emp.salary = 60000;

Combining Static + Private Fields​

class BankAccount {
static accountCount = 0; // shared across all accounts
#balance = 0; // private to each account

constructor(owner, startingBalance = 0) {
this.owner = owner;
this.#balance = startingBalance;
BankAccount.accountCount++;
}

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

getBalance() {
return this.#balance;
}

static getTotalAccounts() {
return BankAccount.accountCount;
}
}

const acc1 = new BankAccount("Alice", 100);
const acc2 = new BankAccount("Bob", 50);

console.log(acc1.getBalance()); // 100
console.log(BankAccount.getTotalAccounts()); // 2

Challenges​

1. Person class​

  • Create a Person class with properties name and age.
  • Make two instances and print their details.
💡 Show Answer
class Person{
constructor(name,age){
this.name=name;
this.age=age;
}
}

const person1 = new Person("James", 38);
const person2 = new Person("Susan", 22);
console.log(JSON.stringify(person1));
console.log(JSON.stringify(person2));

2. Add introduce​

  • Add a method introduce() to Person that prints "My name is [name] and I am [age] years old."
💡 Show Answer
class Person{
constructor(name,age){
this.name=name;
this.age=age;
}
introduce(){
return `My name is ${this.name} and I am ${this.age} years old`;
}
}

3. Book with getSummary​

  • Create a Book class with properties title and author, and a method getSummary().
💡 Show Answer
class Book{
constructor(title,author,year){
this.title=title;
this.author=author;
this.year=year;
}
getSummary(){
return `${this.title} by ${this.author}`;
}
}

4. Rectangle getArea​

  • Write a Rectangle class with width and height.
  • Add a getArea() method.
💡 Show Answer
class Rectangle{
constructor(w,h){
this.width=w;this.height=h;
}
getArea(){
return this.width*this.height;
}
}

5. Add getPerimeter​

💡 Show Answer
class Rectangle{
constructor(w,h){
this.width=w;
this.height=h;
}
getArea(){
return this.width*this.height;
}
getPerimeter(){
return 2*(this.width+this.height);
}
}

6. Student with calculateAverage​

  • Create a Student class with name and grades (array).
  • Add a method calculateAverage().
💡 Show Answer
class Student{
constructor(name,grades){
this.name=name;
this.grades=grades;
}
calculateAverage(){
return this.grades.reduce((a,b)=>a+b,0)/this.grades.length;
}
}

7. BankAccount private balance​

  • Create a BankAccount class with a private field #balance and methods deposit(), withdraw(), and getBalance().
💡 Show Answer
class BankAccount{
#balance=0;
constructor(owner,b=0){
this.owner=owner;
this.#balance=b;
}
deposit(a){
this.#balance+=a;
}
getBalance(){
return this.#balance;
}
withdraw(amount) {
if (amount > this.#balance) {
throw new Error("Insufficient funds");
}
this.#balance -= amount;
}
}

8. Car with mileage​

  • Create a Car class with a private #mileage.
  • Add a method drive(km) and getMileage().
💡 Show Answer
class Car{
#mileage=0;
constructor(make){
this.make=make;
}

drive(d){
this.#mileage+=d;
}

getMileage(){
return this.#mileage;
}
}

9. Private field error​

  • Demonstrate that private fields cannot be accessed outside a class by trying to print them directly.
💡 Show Answer
car.#mileage // SyntaxError: Private field '#mileage' must be declared in an enclosing class

10. Circle with pi​

  • Create a Circle class with property radius and private property #pi = Math.PI.
  • Add methods getArea() and getCircumference() that use the private value.
💡 Show Answer
class Circle {
#pi = Math.PI;
#radius = 0;
constructor(r) {
this.#radius = r;
}
getArea() {
return this.#pi * this.#radius ** 2;
}
getCircumference() {
return 2 * this.#pi * this.#radius;
}
}

const circle = new Circle(5);
console.log(circle.getArea()); // 78.53981633974483
console.log(circle.getCircumference()); // 31.41592653589793