Create a Wallet function that can be called multiple times & maintain balance and transactions, we should be able to call it in a chain way. example is 👇
Wallet(); // prints nothing or its up to you whatever you want to print.
Wallet().getBalance(); // Balance is 0.
Wallet().add(50).add(70).getBalance(); // Added 50. Added 70. Balance is 120.
Wallet().showTransactions(); // +50 <<Date time>>. +70 <<Date time>>.
Wallet().spend(20).getBalance().spend(40).getBalance() // Spent 20. Balance is 100. Spent 40. Balance is 60.
Wallet().showTransactions(); // +50 <<Date time>>. +70 <<Date time>>. -20 <<Date time >>. -40 <<Date time >>.
Wallet().spend(20000); // Error Insufficient Balance.
Wallet().add(-100); // Error negative balance can't be added...
Here we need to maintain balance
and transactions
throughout all the calls of Wallet()
, when this function is called multiple times (ie on new lines as well), that time also we must have original refernce of balance
and transactions
array.
By original reference I mean, reference which was created 1st time.
1 solution is we keep these 2 variables in global context. then solution looks like this.
Solution 1 - Use global variables
var balance = 0;
var transactions = [];
function Wallet() {
const obj = {
add, spend, getBalance, showTransactions,
};
function add(value) {
/* throw error if value is <= 0 */
transactions.push(`+${value} - ${new Date()}`);
balance += value;
console.log(`Added ${value}`);
return obj;
}
function spend(value) {
/* throw error if value > balance */
transactions.push(`-${value} - ${new Date()}`);
balance -= value;
console.log(`Spent ${value}`);
return obj;
}
function getBalance() {
console.log(`Balance is ${balance}`);
return obj;
}
function showTransactions() {
console.log(transactions.join('\n'));
return obj;
}
return obj;
};
Limitations of solutions 1 We can't export this function as module as balance and transactions are global.
We can use concept of function returns function in 1 more possible way. Lets assume Wallet is returned from parent function and that parent function takes care of all the balance
and transactions
variables, now we can export the Wallet
function without any concern.
Solution 2
function getWallet() {
var balance = 0;
var transactions = [];
const obj = {
add,
spend,
getBalance,
showTransactions,
};
function add(value) {
/* throw error if value is <= 0 */
transactions.push(`+${value} : ${new Date()}`);
balance += value;
console.log(`Added ${value}`);
return obj;
}
function spend(value) {
/* throw error if value > balance */
transactions.push(`-${value} : ${new Date()}`);
balance -= value;
console.log(`Spent ${value}`);
return obj;
}
function getBalance() {
console.log(`Balance is ${balance}`);
return obj;
}
function showTransactions() {
console.log(transactions.join('\n'));
return obj;
}
function W() {
return obj;
}
return W;
};
Wallet = getWallet();
/* export Wallet, not getW*/
Concepts you need to know are
- function currying
- function hoisting
- closures
There can be multiple ways to solve this problem as no one is perfect and there is nothing like perfect solution.
Happy Coding. 😊