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()toPersonthat 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
widthandheight. - 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
nameandgrades(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
#balanceand methodsdeposit(),withdraw(), andgetBalance().
💡 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)andgetMileage().
💡 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()andgetCircumference()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