1

First of all, the way the function is being called throws me off. How can a function be called with two separate parens like the one in this example?

addTogether(4)(3)

Lastly, could someone please explain how the closure works in this if statement(please see full code below)?

          if(a) {
              return function(y) {                    
                if(checkIfNum(y)) {         
                    return a + y;
                } else {
                    return undefined;
                }
              };

If we call addTogether() like this: addTogether(4)(3), I understand that argument a is set to 4 but not sure how y is set to 3.

function addTogether() {
    function checkIfNum(num) {
        return typeof num === 'number' ? num : undefined;
    }

    var a = checkIfNum(arguments[0]);
    var b = checkIfNum(arguments[1]);//if there is no second argument, var b = undefined;

    if(arguments.length > 1) {
        return a && b ? a + b : undefined;
    } else {
        if(a) {
            return function(y) {                    
                if(checkIfNum(y)) {         
                    return a + y;
                } else {
                    return undefined;
                }
            };
        } else {
            return undefined;
        }
    }
} 

console.log(addTogether(4)(3));//7

On the first invocation, addTogether(4), 'var a = checkIfNum(arguments[0]);' resolves to 'var a = 4'. The first invocation of addTogether() causes our anonymous function (y) to be invoked and returned to the main function addTogether(). When anonymous function (y) is invoked, JavaScript searches for the value of 'y'. How does JavaScript decide that '3' will be the value of 'y'? My guess is that on the first invocation of addTogether() or addTogether(4), the argument object associated with addTogether() is set to the value of 4. Once 4 gets passed to the function addTogether(), we now have 'a' = 4 trapped in the closure created by addTogether() and at the same time, essentially we have three things happening : #1 : 'a' = 4, # 2 : the argument of addTogether() is now set to the value of 3 or addTogether(3), #3 : anonymous function (y) is returned and invoked causing JavaScript to search for the value of 'y'. JavaScript sees that at this exact point in time, the argument of addTogether() is set to the value of 3 so JavaScript sets the value of 'y' to 3. How does JavaScript know to set 'y' to the value of 3? When a function is invoked inside another function, does JavaScript automatically set the value of the argument of the, for lack of better words, "child" function to the value of the argument of the "parent" function? Is there something about the arguments object that I'm missing here?

wallwalker
  • 591
  • 7
  • 14
  • 27
  • Think of `addTogether(4)(3)` as a shortcut to `var resultOfAddTogether4 = addTogether(4); resultOfAddTogether4(3);` - that is, the `addTogether(4)` part returns another function that can be called in turn. – nnnnnn Sep 07 '17 at 03:37

1 Answers1

3

Great question. I remember scratching my head over this same example about two years ago.

For your first question, "How can a function be called with two separate parens like the one in this example?":

This is only possible because addTogether returns another function. You then pass that function another integer 3. It then adds them up to give you 7.

Then you ask about closures: a closure is formed when you add additional scope inside a scope giving the inner scope access to values in the outer scope. In this case a closure is formed when you declare a function within a function.

For your second question: "I understand that argument a is set to 4 but how y is set to 3":

Here's the logic of the function addTogether:

1) Check if one or two arguments are supplied.

2) If two arguments are supplied return the addition of the numbers iff they are both numbers.

3) If there is just one, return an anonymous function which takes an integer and adds its input to a variable a available to the anonymous function because of it being enclosed inside an outer function which declares a.

This is where the closure is formed. This anonymous function, since it is inside the scope of the outer function addTogether has access to all of the outer function's properties including a and the method checkIfNum.

In your actual case:

1) You supply one argument 3 so addTogether returns an anonymous function.

2) You call this anonymous function with a value of 3. This ends up running the logic in the anonymous function, first checking if 3 is a number, then adding 3 to 4, return 7.

I love JavaScript.

Govind Rai
  • 14,406
  • 9
  • 72
  • 83
  • When a function is invoked inside another function, does JavaScript automatically set the value of the argument of the, for lack of better words, "child" function to the value of the argument of the "parent" function? Is there something about the arguments object that I'm missing here? – wallwalker Sep 07 '17 at 12:14
  • You've got the right theory but that's not how closures work. The compiler is not silently passing hidden arguments to the inner function. It's all about execution context. When an inner function is executed the JavaScript engine makes it so that the inner function has access to its outer execution contexts. Variable `a` is not defined in the inner function so the javascript engine looks into the inner function's outer contexts. It finds a variable `a` defined in `addTogether` and that is how a value is associated to `a`. All values, funcs, objs in outer contexts are referenced from memory. – Govind Rai Sep 07 '17 at 15:34
  • Thank you for the explanation. What is actually happening when the anonymous function is returned? When this anonymous function is invoked and JavaScript searches for the value of 'y' it sees the value of 'y' as the current argument as in `addTogether(3)`? – wallwalker Sep 08 '17 at 11:06
  • Another question : say we only add one thing to our function addTogether() by declaring a variable inside the addTogether() function. We will call it var myVar = 8; When the anonymous function is invoked, JavaScript will look for the value of 'y'. Why does JavaScript choose the value of 3, our current argument value or addTogether(3);, and not some other value like myVar = 8; that is sitting in the execution context created when addTogether() was invoked? – wallwalker Sep 08 '17 at 11:17