0

We have functions created for doing all possible different arithmetic operations on two passed numbers:

function add(a, b){return a + b}
function mul(a, b){return a * b}

...

Now what would be the implementation of wrapper function so wrapper function should do what the third argument asks it to do.

function wrapper(a,b,..){
 ? 
}

for an instance, if i call:

var test = wrapper(4,5,..)

test value should be based on the third argument

indar
  • 90
  • 1
  • 10
  • So, you want to call something like 4, 5, and add and get the result 9, is that correct? – VLAZ Dec 10 '18 at 15:21
  • 4
    `function wrapper(a,b,op) { return op(a, b) }` – Patrick Roberts Dec 10 '18 at 15:21
  • 2
    Possible duplicate of [Pass a JavaScript function as parameter](https://stackoverflow.com/questions/13286233/pass-a-javascript-function-as-parameter) – Anthony Raymond Dec 10 '18 at 15:22
  • yes @vlaz but the condition is as a user we have control over only third argument which tells exactly to wrapper function what is it supposed to do with these two argument. and without using conditionals. – indar Dec 10 '18 at 15:26
  • I disagree with this being a duplicate. The question is not *strictly* about passing functions - it's for controlling the behaviour via a parameter. You can implement this via a callback (as the suggested dupe) but also with a switch, lookup tables, if statements and other ways. So the dupe is too restrictive on the scope. – VLAZ Dec 10 '18 at 15:35

1 Answers1

3

You can pass in a function reference as a third argument and use it to calculate the result using the first two arguments:

function add(a, b){return a + b}
function mul(a, b){return a * b}

function wrapper(a, b, callback){
  return callback(a, b);
}


console.log(wrapper(4, 5, add))
console.log(wrapper(4, 5, mul))

Note how there are no brackets when you pass add or mul as an argument - this is because if you do add(), you would execute the function and you would pass the result of that function. In the case of add(), you would add together undefined and undefined because nothing is passed in, wrapper(4, 5, add()) actually results in wrapper(4, 5, NaN)

An alternative is to use identifiers for the operations. This might be useful if you can't directly pass the function but instead pass data as an action - for example, a user clicks a button on one machine and you send the instruction to a different machine to process. Alternatively, you can save the action in a database or a cookie or any storage and re-play it at a later time. You won't pass the entire logic but just the intended action and you can look it up afterwards. Here is an example of how this can work:

//mapping of action name to logic that will be executed
var actionLookupTable = {
  "addition": add,
  "multiplication": mul
}

function defaultAction() { /* a no-op */}

function add(a, b){return a + b}
function mul(a, b){return a * b}

function wrapper(a, b, actionName){
  //fetch the logic to execute for the action. 
  //If the action name is not recognised, use a default one otherwise you will get an error
  var logic = actionLookupTable[actionName] || defaultAction;
  return logic(a, b);
}


console.log(wrapper(4, 5, "addition"));
console.log(wrapper(4, 5, "multiplication"));
console.log(wrapper(4, 5, "division")); //no implementation but no error is raised
VLAZ
  • 26,331
  • 9
  • 49
  • 67
  • Thanks @vlaz. This was so simple. It's a mix of plain closure and callback. when I had been asked in interview I couldn't think of this simple approach thinking there would be some rocket science involved. anyway thanks. I totally appreciate it. – indar Dec 10 '18 at 15:37
  • @indar I'd say these two are the most common ways to implement this - either pass a function or something to signify what to execute. You can also do more with object oriented approaches but it'd be a bit of an overkill. If you were asked this question, I'd *expect* the asker was interested in the first approach. But the second one is still valid - it allows you to decouple implementation from intention and is more flexible. As I said, you can use it to record the *intended* actions and then execute them separately - this can be used to provide an undo functionality, for example. – VLAZ Dec 10 '18 at 15:44