In ES6 (ECMAScript 2015), getters and setters are special methods that allow you to define how to retrieve and set the values of an object property. They are primarily used to encapsulate the logic of getting or setting a property, providing more control over the internal state of an object.

Here’s a detailed explanation with examples:

What are Getters and Setters?

  • Getter: A function that retrieves (gets) the value of a property.
  • Setter: A function that sets (updates) the value of a property.

These are defined within an object using the get and set keywords.

Why Use Getters and Setters?

  • Encapsulation: Control access to properties and encapsulate logic.
  • Validation: Add checks or constraints when a property is set.
  • Computed Properties: Dynamically compute the value of a property when it’s accessed.
  • Debugging/Logging: Add logging or perform operations during a property access or update.

Syntax

const obj = {
    // Getter
    get propertyName() {
        // Code to retrieve the value
    },

    // Setter
    set propertyName(value) {
        // Code to set/update the value
    }
};

Example: Basic Usage

const person = {
    firstName: "John",
    lastName: "Doe",

    // Getter for fullName
    get fullName() {
        return `${this.firstName} ${this.lastName}`;
    },

    // Setter for fullName
    set fullName(name) {
        const [first, last] = name.split(" ");
        this.firstName = first;
        this.lastName = last;
    }
};

// Using the getter
console.log(person.fullName); // John Doe

// Using the setter
person.fullName = "Jane Smith";
console.log(person.firstName); // Jane
console.log(person.lastName);  // Smith
console.log(person.fullName);  // Jane Smith

Example: Adding Validation with Setters

const account = {
    _balance: 0, // Private property convention using "_"

    // Getter for balance
    get balance() {
        return this._balance;
    },

    // Setter for balance with validation
    set balance(amount) {
        if (amount < 0) {
            console.error("Balance cannot be negative!");
        } else {
            this._balance = amount;
        }
    }
};

// Trying to set a negative balance
account.balance = -100; // Balance cannot be negative!

// Setting a valid balance
account.balance = 500;
console.log(account.balance); // 500

Example: Using Getters and Setters in Classes

In ES6, getters and setters can also be used in classes to encapsulate property logic.

class Rectangle
{
    constructor(width, height)
    {
        this.width = width;
        this.height = height;
    }

    // Getter for area
    get area()
    {
        return this.width * this.height;
    }

    // Setter for dimensions
    set dimensions({ width, height })
    {
        if (width > 0 && height > 0) {
            this.width = width;
            this.height = height;
        } else {
            console.error("Dimensions must be positive numbers!");
        }
    }
}

const rect = new Rectangle(10, 20);

// Accessing the area using getter
console.log(rect.area); // 200

// Updating dimensions using setter
rect.dimensions = { width: 15, height: 25 };
console.log(rect.area); // 375

// Invalid dimensions
rect.dimensions = { width: -5, height: 10 }; // Dimensions must be positive numbers!

Example: Advanced Use Case with Computed Properties

const temperature = {
    _celsius: 0,

    // Getter for Fahrenheit
    get fahrenheit() {
        return (this._celsius * 9) / 5 + 32;
    },

    // Setter for Fahrenheit
    set fahrenheit(value) {
        this._celsius = ((value - 32) * 5) / 9;
    }
};

// Accessing in Fahrenheit
temperature._celsius = 25;
console.log(temperature.fahrenheit); // 77

// Setting Fahrenheit and updating Celsius
temperature.fahrenheit = 86;
console.log(temperature._celsius); // 30

Using getters and setters in JavaScript allows for cleaner, more maintainable code by providing controlled access and manipulation of object properties. They add abstraction, making objects more robust and easier to work with.