Subjects

All subjects Django Java Python React Spring Boot JavaScript PHP
Sign Up Free
Question 10 of 10 · Object-Oriented JavaScript
Interview question

How do you implement encapsulation in JavaScript before private fields existed (using closures)? Private fields के आने से पहले closures से encapsulation कैसे implement करें?

Answer

Before the # syntax was standardized, closures were the primary way to achieve true data privacy - variables inside a constructor function that are never attached to 'this' are inaccessible from outside.

// Closure-based encapsulation - the classic pre-# approach
function BankAccount(initialBalance) {
    let balance = initialBalance; // truly private - not attached to 'this'
    const transactionHistory = [];

    this.deposit = function(amount) {
        balance += amount;
        transactionHistory.push({ type: 'deposit', amount });
        return balance;
    };

    this.withdraw = function(amount) {
        if (amount > balance) {
            throw new Error('Insufficient funds');
        }
        balance -= amount;
        transactionHistory.push({ type: 'withdraw', amount });
        return balance;
    };

    this.getBalance = function() {
        return balance; // controlled read access
    };

    this.getHistory = function() {
        return [...transactionHistory]; // return a copy, prevent external mutation
    };
}

const account = new BankAccount(100);
account.deposit(50);
console.log(account.getBalance()); // 150

console.log(account.balance); // undefined - truly inaccessible, not just convention

// Comparison with the modern private field syntax
class ModernBankAccount {
    #balance;
    #transactionHistory = [];

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

    deposit(amount) {
        this.#balance += amount;
        this.#transactionHistory.push({ type: 'deposit', amount });
        return this.#balance;
    }

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

// Trade-off: closures create a new function per instance (memory cost per method),
// while class methods on the prototype are shared - # fields give privacy
// WITHOUT this memory overhead, which is why they're preferred today

# syntax standardize होने से पहले, closures true data privacy पाने का मुख्य तरीका था - constructor function के अंदर वो variables जो 'this' से attach नहीं हैं, बाहर से inaccessible होते हैं।

// Closure-based encapsulation - classic pुराना approach
function BankAccount(initialBalance) {
    let balance = initialBalance; // truly private
    const transactionHistory = [];

    this.deposit = function(amount) {
        balance += amount;
        transactionHistory.push({ type: 'deposit', amount });
        return balance;
    };

    this.withdraw = function(amount) {
        if (amount > balance) throw new Error('Insufficient funds');
        balance -= amount;
        transactionHistory.push({ type: 'withdraw', amount });
        return balance;
    };

    this.getBalance = function() {
        return balance;
    };

    this.getHistory = function() {
        return [...transactionHistory];
    };
}

const account = new BankAccount(100);
account.deposit(50);
console.log(account.getBalance()); // 150
console.log(account.balance); // undefined - truly inaccessible

// Modern private field syntax से comparison
class ModernBankAccount {
    #balance;
    #transactionHistory = [];

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

    deposit(amount) {
        this.#balance += amount;
        this.#transactionHistory.push({ type: 'deposit', amount });
        return this.#balance;
    }

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

// Trade-off: closures हर instance में नया function बनाते हैं (memory cost),
// जबकि class methods prototype पर shared होते हैं - # fields बिना इस
// overhead के privacy देते हैं, इसीलिए आजकल preferred हैं

Was this answer clear?