2

I have found this example of a closure on codeproject but it does not explain how it works.

    function getMultiplier(multiplyBy){
       function multiply(num){
          return multiplyBy * num;
       }
 
       return multiply;
    }
 
    var multiplyByTwo = getMultiplier(2);
    var multiplyByTen = getMultiplier(10);
    var twoIntoFive = multiplyByTwo(5); 
    var tenIntoSix = multiplyByTen(6);  

    console.log(twoIntoFive); // 10
    console.log(tenIntoSix); // 60

Now i am going to assume, with my C brain what is happening. Please correct me or give your explanation.

  1. functions in javascript can also be objects, so the inner function multiply(num) is a method of getMultiplier, looking from outside.
  2. var multiplyByTwo is assigned the return value of function getMultiplier when invoked with argument 2.
  3. when you call getMultiplier(2), javascript interpreter creates an object in memory based on the definition of getMultiplier().
  4. that object has a method multiply and it's address is assigned to variable multiplyByTwo.
  5. var twoIntoFive = multiplyByTwo(5); calls the getMultiplier(2) object's method multiply(num) with argument 5.
  6. that returns simple numeric 10 into variable twoIntoFive
  7. multiplyByTwo = 0; will make the garbage collector of javascript delete object getMultiplier(2) from memory.
Tom M
  • 2,815
  • 2
  • 20
  • 47
  • Take a look here [How do JavaScript closures work?](https://stackoverflow.com/questions/111102/how-do-javascript-closures-work?rq=1) – Yordan Nikolov Aug 01 '17 at 14:31
  • You can refer to this link to know more about closures. https://developer.mozilla.org/en/docs/Web/JavaScript/Closures – Rajesh P Aug 01 '17 at 14:35
  • Yes. Just *method* is wrongly used here (and object if its in the sense of js object) @downvoter are you serious?? – Jonas Wilms Aug 01 '17 at 14:35
  • 1
    @georg unnecessary close. Requesting reopen. The linked question explains how closures work but does not answer op's specific questions. – Tom M Aug 01 '17 at 15:25
  • 1
    @TomM: the dupe appears exhaustive and I doubt there's anything new to say, but let's give it a try! – georg Aug 01 '17 at 15:27
  • @georg thank you, I understand your point and agree that it is pretty much exhaustive in regard of closures. But as I said OP had specific questions regarding his specific piece of code and I doubt that the dupe answers all of these. I did not want to appear rude but in my opinion many questions get closed too fast which makes stackoverflow pretty toxic to new users – Tom M Aug 01 '17 at 15:41

3 Answers3

1

Actually multiply is just a function and not a method in terms of OOP.

Basically function are objects, but callable. In this case, it is not a question if a function is an object, but more if you can hand over a reference to a function. This is possible and done with return multiply.

After calling getMultiplier with a value for the parameter, the value is stored and a function is returned (and assigned).

Then you need to call the function, which reference is stored in multiplyByTwo.

The local variable multiplyBy is used to return a result. No object is created.

Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • But multiplyByTwo and multiplyByTen both reference the same function multiply(num), if no objects are created in memory where does multiply(num) get the corresponding value of multiplyBy? Simply calling a reference of multiply(num) will have multipleBy undefined. –  Aug 01 '17 at 15:12
  • it generates a new local scope for the variables inside. with returning the function, the scope is saved for it. – Nina Scholz Aug 01 '17 at 15:18
  • @b'stard - no, they reference different functions. The function (or objects, if you'd like to call them that, which they are) are created and returned every time you call `getMultiplier`. Do this `getMultiplier(2) == getMultiplier(10)` - it's false - they are different objects – Adam Jenkins Aug 01 '17 at 15:39
  • A new local scope for the variables inside based on the definition of getMultiplier(multiplyBy) is some sort of an object in memory. But where? And what symbol does it use to reference this place in memory? Furthermore it creates two of this in memory. One for multiplyByTwo and one for multiplyByTen. They must be the symbols for the new objects that multiply(num) has access on. The internal representation of the inner function multiply(num) has to have some hidden pointer to getMultiplier objects, just like C++ functions have the hidden this pointer of the object. –  Aug 01 '17 at 15:43
  • This might be semantics, but `multiply` doesn't need to know about `getMultiplier` per se, it just needs to know what is available in it's local scope (which happens to be the same as the scope created when `getMultiplier` gets called). The JS runtime obviously keeps track of this scope, but I haven't encountered an engine that provides a mechanism for you to access the scope. – Adam Jenkins Aug 01 '17 at 15:46
  • @Adam - something like that. I use the C term for an object - a data type that occupies real memory location. –  Aug 01 '17 at 15:47
0

Interesting questions.

  1. Almost correct, except that on a basic level, in javascript in fact all functions are objects. Also, looking at the latter two variables, twoIntoFive and tenIntoSix, multiply() is a standalone Function in the scope of getMultiplier() (meaning it also holds a reference to variables inside that function).

  2. Exactly

  3. Correct, but keep in mind that it still differs from getMultiplier.

  4. As explained in this article, rather than a object, javascript creates an interface with a reference to the already declared variables inside the function.

  5. This is how it seems to work. But twoIntoFive actually calls the returned interface that references the getMultiplier() function parameter

  6. Correct.

  7. This is correct. Since you removed the reference to the interface, it will be deleted.

Further Reading

It's generally a good idea to refer to MDN when having questions about javascript. It's the most complete documentation I have read so far.

Feel free to correct me or give some feedback if you find errors in my answer or have further questions

Tom M
  • 2,815
  • 2
  • 20
  • 47
  • I was wrong about 3, 4 and 5. because C doesn't have nested functions I presumed that an object of getMultiplier is created on the heap with it's member variables, but that does not give you access to the argument. Pascal call to a nested function has one additional information in the stack frame of the nested function, that is the pointer to the stack frame of the outer function. you need two pointers to call a nested function, they are passed to multiplyByTwo as a return value from getMultiplier(multiplyBy). one for the stack frame of getMultiplier(2) and the other to multiply(num). –  Aug 02 '17 at 10:38
  • the garbage collector marks that multiplyByTwo has a reference to that stack frame and does not automatically free it upon return from getMultiplier(2). then a call to multiplyByTwo(5) equals multiply(5) passing the pointer to the stack frame of getMultiplier(2). is this what can be said to be happening here? –  Aug 02 '17 at 10:52
  • The link doesn't work for me. Yeah the ability to either reference and execute a function while declaring a variable is kind of confusing, – Tom M Aug 03 '17 at 14:10
  • (...) "then a call to multiplyByTwo(5) equals multiply(5) passing the pointer to the stack frame of getMultiplier(2). is this what can be said to be happening here?" I'm not sure about this but it seems like it when you run the script in the debugger. – Tom M Aug 03 '17 at 14:13
  • this explanation of nested functions is the best for understanding closures http://www.drdobbs.com/architecture-and-design/how-nested-functions-work-part-2/228701866 –  Aug 04 '17 at 09:39
-1

Basically a function is a function. I wouldn't say multiply(num) is a getMultiplier's method, it is just declared in its body.

Maybe this way it would be easier to understand?

var x = function getMultiplier(multiplyBy){
   var y = function (num){
      return multiplyBy * num;
   }

   return y;
}

Anyways. The way it works is: calling getMultiplier returns a function "multiply". The multiply function returns multiplyBy * num, but getMultiplier returns sort of a pre-made multiply function which has multiplyBy already substituted by getMultiplier's parameter.

Thus, when you called getMultiplier(2), what you get under multiplyByTwo variable is:

function multiply(num){
   return 2 * num;
}

Since getMultiplier(num) simply substitutes a parameter inside returned multiply function, you can pass it literally anything and nothing will be deleted.

Scharnvirk
  • 339
  • 1
  • 7