Skip to content

Instantly share code, notes, and snippets.

@joshwyatt
Created April 26, 2017 20:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joshwyatt/644773cde1069111781904e55a089a22 to your computer and use it in GitHub Desktop.
Save joshwyatt/644773cde1069111781904e55a089a22 to your computer and use it in GitHub Desktop.
Bank Account example for private variables accessed through getters and setters

There are situations in OOP where we may wish to protect access to instance properties.

In the following example we will make a bank account constructor in the hopes that by including a pin, will be protected.

const BankAccount = function(initialBalance, pin) {
  this.balance = initialBalance;
  this.pin = pin;
}

BankAccount.prototype.withdrawl = function(pin, amount) {
  if (pin === this.pin) {
    this.balance -= amount;
  }
}

BankAccount.prototype.deposit = function(pin, amount) {
  if (pin === this.pin) {
    this.balance += amount;
  }
}

let account = new BankAccount(100.00, 1234);

Unfortunately, anyone can access both the pin and the balance directly, which is a big security problem.

let stolenPin = account.pin;
let stolenMoney = account.balance
account.balance = 0;

console.log(`Here is the stolen PIN: ${stolenPin}`);
console.log(`Here is the stolen money: ${stolenMoney}`);

Rather than definine properties that we want to be private on this where they can be accessed by anyone, we declare them as varables.

In conjunction with defining the properties as variables, we must now define our functions within the constructor, instead of on the constructor's prototype, so that they are closures, with continued acces to the private variables.

const SecureBankAccount = function(initialBalance, pin) {
  // balance is NOT defined as a property on `this`
  let balance = initialBalance;
  // pin is also defined because it is passed in as an argument

  // These functions can access `balance` and `pin` because they are closures.
  // In order to create these closures, we cannot define them on the
  // constructor's `prototype`
  this.withdrawl = function(pinAttempt, amount) {
    if (pinAttempt === pin) {
      balance -= amount;
    }
  }

  this.deposit = function(pinAttempt, amount) {
    if (pinAttempt === pin) {
      balance += amount;
    }
  }

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

let secureAccount = new SecureBankAccount(100, 1234)

let foiledAttemptAtStolenPin = secureAccount.pin; // foiledAttemptAtStolenPin is undefined
let foiledAttemptAtStolenMoney = secureAccount.balance; // foiledAttemptAtStolenMoney is undefined

console.log(`Here is the foiled attempt at stealing the pin: ${foiledAttemptAtStolenPin}`);
console.log(`Here is the foiled attempt at stealing the money: ${foiledAttemptAtStolenMoney}`);

Using the instance methods, which are closures, we can interact with the private variables as intended.

let initialBalance = secureAccount.getBalance(1234);
console.log(`Here is the initial balance after passing in the correct pin: ${initialBalance}`);

secureAccount.deposit(1234, 100);
let balanceAfterDeposit = secureAccount.getBalance(1234);
console.log(`Here is the balance after deposit after passing in the correct pin: ${balanceAfterDeposit}`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment