In my attempt to understand a very specific aspect of closure in javascript, I felt compelled to illustrate it with an example. This is pulled from MDN's explanation of closure:
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
And this example is touched upon here, but I don't think it resolves my own personal confusion, although my confusion is also related to the value of y.
My question is when add5(2) returns function(y), how does it determine the value of y when y is not explicitly assigned anywhere within or outside of makeAdder(x)? Also, is add5(2) = makeAdder(5)(2)? And if so, how can this function execute when makeAdder(x)(y) is not defined in this example? Also, is there a way that describing it as such might help clarify this issue for someone who's having a hard time internalizing the logic behind closure? It appears as if add5(2) assigns 2 to y, but there's no clear way for me to trace this. Any help is much appreciated. Thank you!
One way to look at this is that
var add5 = makeAdder(5);
var add10 = makeAdder(10);
is essentially equivalent to
var add5 = function(y) {
return 5 + y;
}
var add10 = function(y) {
return 10 + y;
}
Perhaps this helps?
The variable "y" is the parameter of the function returned by a call to "makeAdder". It's value is not set in "makeAdder" because that wouldn't make sense; the whole point is to create a new function that will add a given value ("x") to a parameter ("y").
The returned function takes one argument, "y". When, after calling "makeAdder", code calls the function returned and so passes in a value for "y", the final addition (5 + 2 or whatever) is carried out.
Function call syntax (the parenthesized argument list) is evaluated left-to-right, so
makeAdder(5)(2)
is the same as
(makeAdder(5))(2)
meaning,
call the 'makeAdder' function with the parameter 5, and then when that returns treat its return value as a function reference and call that function with the parameter 2.
My question is when add5(2) returns function(y), how does it determine the value of y when y is not explicitly assigned anywhere within or outside of makeAdder(x)?
The function returned by makeAdder is:
function(y) {
return x + y;
}
where x has already been assigned the value 5.
So there is your y. It's inclusion as a formal parameter in the function expression is effectively the same as declaring it with var, x is initialised the same way in makeAdder.
Also, is add5(2) = makeAdder(5)(2)?
Yes, though I think you meant == (equals), not = (assignment).
And if so, how can this function execute when makeAdder(x)(y) is not defined in this example?
makeAdder returns a function, so the second set of parenthesis causes it to be called with whatever value is provided (including none):
makeAdder(5)(2) // 7
is the same as:
var foo = makeAdder(5);
var bar = foo(2);
the only difference being that in the second case, the intermediate result is stored as foo before being called.
Also, is there a way that describing it as such might help clarify this issue for someone who's having a hard time internalizing the logic behind closure?
The real power of a closure is that a function can return another function that continues to have the same scope chain it had when it was created, so that it has exclusive access to local variables of all the execution contexts on its scope chain (other than global variables, they aren't exclusive) after those functions have finished executing. Complex inheritance structures can be created with closures (not recommended though).
It's this persistence that makes a closures really useful, and not just scope chain resolution.
Related
In the simple, 2 layer currying example below the word dog is passed into the y argument.
"use strict";
function layer2(x) {
return function(y) {
return console.log(x, y);
}
}
var layer1 = layer2('cat');
layer1('dog');
I know it works this way and I can reliably reproduce this. However I can't understand the mechanics of why this works. If I made a 100 layer example layer 1 would be the innermost function and the pattern would work outwards from that point. What piece of basic mechanics causes this? Thanks so much for any input!
In short, lexical scoping is what makes this possible. See, layer2 function in your example returns another function that has two variables in its scope:
y - its own argument
x - parameter passed into `layer2` function
The key point here is that once you store that returned function, x value is set and will never change. Again, in terms of your example, function stored in layer1 variable - result of layer2('cat') - has x name bound to 'cat' string value.
It's simple. When you call layer2('cat') it will return the function:
function(y) {
return console.log(x, y);
}
Now, layer1('dog') returns function call return console.log(x,y); on which x is received already in a call layer2('cat'), and y is being called from function(y).
Here's a very good read blog https://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/ which will help you further.
What should be the value of final_answer in this Js code snippet and why?
function weird(x) {
var tmp = 3;
return function(y) {
return x + y + ++tmp;
}
}
var funny = weird(2);
var final_answer = funny(10);
I think value of final_answer is funny(10) because even though funny is 2+4+2 that is 8 but since that value is stored in a variable, we cannot call a variable like a function.
I don't know whether I'm correct or not.. If i'm wrong then please specify the reason why so that i can understand and not repeat this mistake.
When var funny = weird(2) is called, inside the function weird two variables are created, x with the value of 2 and tmp with the value of 3. Then a function object is created with the return statement. Code inside this function can access variables x and tmp. As this function object is then returned and assigned to variable funny which resides outside the function weird, a closure is created. This means that even though code outside of weird normally cannot access variables inside weird, the function object assigned to funny can do so.
As you call funny(10), the code calculates the sum of x with the value of 2, y with the value of 10 and the pre-incremented value 4 of tmp. So the final result is 16.
weird returns a function, which references the argument passed to weird. This is stored as funny. Calling funny (with an argument) calls the function returned from weird.
funny = weird(2);
funny(10)
>16
funny(5)
>12
funny(100)
>108
In other words, funny is the product of an anonymous function, and can be treated as though it were defined using function.
This is a fragment of code I've found from a tutorial, but I can't understand clearly it's purpose. Here is the example:
app.js
var oojs = (function(oojs){
return oojs;
}(oojs || {}));
The first part I'm confused is why it is called with the same parameter as it's argument?
The second doubt is why if there is no "oojs" should call the function with an object literal as parameter? Is this necessary?
Finally why it should return the same as it's function name (oojs).
Maybe it's a way to create an object, but if someone could help me the need of this I will really appreciate.
This is just scoping rules in JavaScript. Whenever a new function is created, a new variable scope is created. The parameter name oojs is indeed the same identifier as the outside parameter oojs but it's more local.
Here is a simplified example
function foo(x){
console.log(x + 2);
}
var x = 3; // this is a different x, it belongs to the outer scope, and not the function
foo(x); // logs 5, since x is passed to the function, then x + 2 is logged
In this code example, the idea is to only change oojs if it doesn't exist, and then set it to the return value of the immediately invoked function expression. It's similar to a composing module pattern. Personally, I find the syntax rather confusing to read when a lot of lines are involved.
How does greaterThanTen(9) become the y variable in the return function? What I mean is how does the parameter (9) become the y in the return function argument? Wouldn't 9 be replaced with x since greaterThanTen = greaterThan(10)? Wouldn't the 9 just replace the x = 10 parameter? I just don't understand how that 9 parameter is getting to y in the return function.
function greaterThan(x) {
return function(y) {
return y > x;
};
}
var greaterThanTen = greaterThan(10);
show(greaterThanTen(9));
It doesn't "become the y variable". The function greaterThan returns a function, and the value passed to greaterThan is "captured" in that returned function.
In other words, greaterThan(10) creates the following function:
function(y) { return y > 10; }
It's similar to writing:
function greaterThan10(y) { return y > 10; }
Functions that create functions take advantage of closures ("the thing that 'captures' the 10).
The advantage is that you don't need to keep writing greaterThanNnn functions for every number you want to use, you just call greaterThan(n) for whatever you need. This is a contrived, but popular, example, of course.
For chunks of info relating to referencing functions, when to use () and when not to, and some more realistic examples, see also:
Difference between calling function and referencing function?
When do I use parenthesis and when do I not?
Why function statement requires a name?
when you called greaterThan(10) it assigned value of x and return the function in greaterThanTen variable which now becomes
var greaterThanTen = function(x){10>x};
then in next line you called greaterThanTen(9) so it will assign the x value. i hope you understood what i said.
You must have to know the basis about the closures concept in JavaScript. Closures are the most tricky and special addition to the JavaScript language. As you will notice they follow the lexical scope of the language flow. Here in this example;
function greaterThan(x) {
return function(y) {
return y > x;
};
}
var greaterThanTen = greaterThan(10);
console.log(greaterThanTen(9));
If you see there is the main concept of closures. Once you call the function greaterThan it creates another function. But as you pass the first argument 10, it takes the place of x. Further when you call the function and pass the second argument 9
it takes place on y the function built inside. In this way the values are stored in the function call stack and you can compare and operate on those values.
function makeIncreaseByFunction(increaseByAmount) {
return function (numberToIncrease) {
return numberToIncrease + increaseByAmount;
};
}
makeIncreaseByFunction(3)(10);
Updated for Clarity
Can somebody explain why the (3)(10) is written the way it is? I understand that 10 is being supplied as an argument to the inner function, but why is syntactically notated like this? If we had three nested functions, would the arguments always be written in order as in (3)(10)(20)?
With intermediate variable:
var increaseBy3 = makeIncreaseByFunction(3);
var foo = increaseBy3(10);
Without intermediate variable:
var foo = makeIncreaseByFunction(3)(10);
In both cases, the first invokation passes the argument 3 to makeIncreaseByFunction, and as a result it returns the inner function that has closed over increaseByAmount with the value of 3. Whether you create a variable for the intermediate function returned by makeIncreaseByFunction, or just invoke it directly, it does the same thing.
Can you explain a little bit more detail about how in var foo = makeIncreaseByFunction(3)(10); the 10 is getting to the inner function? It just looks syntactically different from how arguments usually get passed in Javascript to me. – ggg
makeIncreaseByFunction(3) returns a function, specifically the "inner function" defined inside makeIncreaseByFunction. As will all functions, you call it with the function ( arguments ) syntax. You can write it like this if it makes more sense to you this way:
( makeIncreaseByFunction(3) )(10)
What happens here is makeIncreaseByFunction(3) gets called first and returns the ⟪inner function⟫, and then we call ⟪inner function⟫(10).
If you were evaluating this by hand (I think this is what you meant by "syntactically"), you could think of it happening step-by-step like this:
// Original invocation
var foo = makeIncreaseByFunction(3)(10);
// Substitute the definition of makeIncreaseByFunction
var foo = (function (increaseByAmount) {
return function (numberToIncrease) {
return numberToIncrease + increaseByAmount;
};
})(3)(10);
// Apply the parameter 3
var foo = (function (numberToIncrease) {
return numberToIncrease + 3;
})(10);
// Apply the parameter 10
var foo = 10 + 3;
// Final result
var foo = 13;
Note: If you want to be technical, all we're doing here is two Beta reductions—but unless you have background with the Lambda Calculus that will probably confuse you more than it will help you!
makeIncreaseByFunction(3) would return function so the syntax for then calling it with 10 would be makeIncreaseByFunction(3)(10).
This is easy to understand as if you have a function foo (imagine that the return of makeIncreaseByFunction(3) is such a function, they are evaluated identically), you would then call it with 10 using foo(10).
As for how the value of 10 is being 'passed', this is the wrong way to thing about things.
You must realise that in Javascript functions are first class objects.
Instead of passing the value to the inner function, you are creating a function that does what you want and then calling it with the outer argument.
It is the same as using a variable to add within a function in a non-functional language except functions can be dynamically created at runtime and the values of any variable in their definition can be set influencing their internal consistency.
The closure refers to the fact that the created function is a black-box which hides the variable used to initialize it, despite still using that variable to increment the value it is called with.
var increaseBy3 = makeIncreaseByFunction(3); is the exact same as (disregarding the local storage for the variable increaseByAmount):
var increaseBy3 = function (numberToIncrease) {
return numberToIncrease + 3;
};
So of course now you can call increaseBy3(10) and get 13. increaseBy3 just references as anonymous function which returns its first argument plus 3.