Reputation: 31
I have a 'twice' function that return 2 of the argument passed into it. I also have another function 'runTwice' that counts the number of times it called the 'twice' function (the idea being that I want the 'twice' function to only run 'twice' no matter how often it is called via the 'runTwice' function). Can you please help?
Functions are given below:
var count = 1;
function twice(num){
return num*2;
}
function runTwice(func){
if (count<3){
count++;
return func;
} else {
return 'Function cannot run!';
}
}
var myFunc = runTwice(twice)
var output = [];
for (var i = 0; i < 3; i++){
output.push(myFunc(i));
}
console.log(output);
I would like the output to be [0, 2, 'Function cannot run!'].
I can make this work if I count the 'twice' function directly but I am looking to understand why this doesn't work as presented above.
Upvotes: 3
Views: 151
Reputation: 31712
The function runTwice
should return another function that will decide whether to call the function func
(using Function.prototype.apply
) or to return a string message instead:
function twice(num){
return num * 2;
}
function runTwice(func){
var count = 0; // this will be trapped in a closure along with func
return function() { // this is the function that gets called
count++; // it increments its version of the count variable
if(count <= 2) // if count is less than 2
return func.apply(this, arguments); // then it calls the function func with whatever arguments passed into it and return the returned value of that call
return "Not available anymore!"; // otherwise (count > 2), then it returns a string
}
}
var myFunc = runTwice(twice);
for (var i = 0; i < 3; i++){
console.log(myFunc(i));
}
Even better:
You can pass in the number of times allowed as well:
function double(num) {
return num * 2;
}
function triple(num) {
return num * 3;
}
function run(func, times){
var count = 0; // this will be trapped in a closure along with func and times
return function() { // this is the function that gets called
count++; // it increments its version of the count variable
if(count <= times) // if count is less than times
return func.apply(this, arguments); // then it calls the function func with whatever arguments passed into it and return the returned value of that call
return "Not available anymore!"; // otherwise (count > times), then it returns a string
}
}
var double2times = run(double, 2); // double2times can only be called 2 times
var triple5times = run(triple, 5); // triple5times can only be called 5 times
for (var i = 0; i < 10; i++){
console.log("Double:", double2times(i));
console.log("Triple:", triple5times(i));
}
Upvotes: 1
Reputation: 51916
Just for fun I'll make a generic expireAfter(invocable[, times[, message]])
function:
function expireAfter(invocable, times = 2, message = 'Function cannot run!') {
return function expires() {
if (times > 0) {
times--;
return invocable.apply(this, arguments);
}
return message;
}
}
function twice(n) {
return n * 2;
}
var myFunc = expireAfter(twice);
console.log(Array(3)
.fill()
.map((_, index) => myFunc(index))
);
Upvotes: 1