Arguments Optional, oh boy, this is the last challenge before we get to the advanced bonfires section. This bonfire will show us some very interesting facts about JavaScript functions.
For this task, we are asked to write a function that accepts either one or two arguments. If two arguments are provided (and both are numbers), we proceed to return the sum; but, if we are only given a single argument, we must return a function. This returned function will accept one number as argument, and will return the sum of it and the originally passed number. Let’s see a few examples:
addTogether(5, 6); //-> 11 add(11, 53); //-> 64 var addFive = addTogether(5); addFive(6); //-> 11 var addEleven = addTogether(11); addEleven(53); //-> 64
That’s how it should go about it. Now, instead of going straight to the good stuff, let’s set up the bare-bones and return the sum when two numbers are provided. We’ll use the arguments object (you can read about it here and here) since we won’t know if one or two arguments are being passed:
function addTogether() { if (arguments.length === 1 && typeof arguments[0] === 'number') { // If only one argument is provided, and it's a number, do some magic. // Return a function! } else if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') { // For any other number of arguments, make sure that the first two are numbers! return arguments[0] + arguments[1]; } }
Good! Now that the easy part is out of the way, let’s go into the interesting stuff. Returning a function, how is it done? If you did not know already, in JavaScript, functions are treated as any other value, so we can store them in a variable or return them from within another function just as if it were a mere string or number. Let me illustrate with a few examples:
function greet(greeting) { return function(name) { console.log(greeting + ' ' + name + '!'); } } // We can do this: var sayHi = greet('Hi'); sayHi('John'); //-> Hi John! // Or we can do this: greet('Hey')('Mike'); //-> Hey Mike!
The second example may be a bit more obscure, but makes sense once you understand that a variable can hold a function just as it can hold any other value. If you don’t understand this fully yet, don’t worry, practice and repetition are the key to success!
Let’s use this knowledge to finish up this bonfire then. First, we’ll store the function that we want to return in a variable, and then return it (we can actually return the function straight away like shown in the second code snippet). We will also store the given argument in a variable, since using the arguments object inside the function to be returned will not have the same value any more!
function addTogether() { if (arguments.length === 1 && typeof arguments[0] === 'number') { var x = arguments[0]; // We store the given number to use it inside the returned function. var addFunction = function(y) { return x + y; } return addFunction; } else if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') { return arguments[0] + arguments[1]; } }
Here we return the function without using unnecessary variables:
function addTogether() { if (arguments.length === 1 && typeof arguments[0] === 'number') { var x = arguments[0]; return function(y) { return x + y; } } else if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') { return arguments[0] + arguments[1]; } }
But wait! We have a little problem that needs fixing! We’ve been checking every argument and making sure that we only proceed when we get numbers in, that’s good practice and something to always keep in mind, let’s do the same for the inner function too!
function addTogether() { if (arguments.length === 1 && typeof arguments[0] === 'number') { var x = arguments[0]; return function(y) { if (typeof y === 'number') { return x + y; }; } } else if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') { return arguments[0] + arguments[1]; } }
There we go! That marks the end of this bonfire and the start of the advanced algorithm practice, get ready for the real deal!