This question already has answers here:
What is 'Currying'?
(23 answers)
Closed 28 days ago.
I am learning JavaScript and using the Eloquent JavaScript book by Marijn Haverbeke. I don't understand how the below higher order function works, specifically how the variables m and n are assigned.
Please advise.
function greaterThan(n) {
return m => m > n;
}
let greaterThan10 = greaterThan(10);
console.log(greaterThan10(11));
// → true
I've run the code and proven that it works for when m > n (true) and when m < n (false).
First of all, there are multiple concepts you need to understand:
Function declaration is a description of what function accepts and how does it behave. In your example function greaterThan(n) { ... } and m => ... are function declarations.
Function invocation is a request to execute specific function with specific arguments. In you example greaterThan(10) is a function invocation.
Parameters are special local variables that a function accepts and can use later. In your example, n is a parameter of greaterThan function and m is a parameter of the inner function.
Arguments are specific values of parameters passed during function invocation.
Function scope is tougher to explain. It kind of a virtual space containing references to all the variables visible in specific function. For example, greaterThan sees variable n only, but inner m => m > n sees both n and m. That's because of another concept called closure.
Closure - tldr means that inner function can reference variables from all parent scopes, up to global scope.
Now to explaining your case.
function greaterThan(n) {
return m => m > n;
}
This declares a function greaterThan with a single parameter n.
This function returns a closure - anonymous function with single parameter m.
let greaterThan10 = greaterThan(10);
This invokes greaterThan function with 10 as argument. greaterThan returns a closure with n=10. E.g:
let greaterThan10 = m => m > 10;
And finally
console.log(greaterThan10(11));
invokes the function returned by greaterThan with 11 as an argument.
E.g. (m => m > 10)(11) -> 11 > 10 -> true.
The variable n is the parameter to greaterThan(), so it's assigned when that function is called. The function returns another function, one with a parameter called m. That parameter is assigned a value when the returned function is called.
Thus in your example, n gets the value 10 when greaterThan() is called, and then m in the returned function gets the value 11 when that function is called.
Related
I have this problem on freeCodeCamp as I'm learning JavaScript.
I'm trying to understand this block of code.
function multiply(arr, n) {
if (n <= 0) {
return 1;
} else {
return multiply(arr, n-1)*arr[n-1];
}
}console.log(multiply([2,2,4],3));
As a whole, I understand what this code above does. But not this line below.
multiply(arr, n-1)*arr[n-1];
There's already a about post this specific problem here, but I have read all of the comments and I did not understand.
What I don't understand specifically is (arr, n-1). Exactly what does that do? The rest of the line I can understand after a long time thinking, it's just that little piece that I can't make sense of.
What I don't understand specifically is "(arr, n-1)". Exactly what does that do?
This is the argument list for the function call of the multiply() function. You cannot understand this in isolation because it belongs to the function call.
In other words, the syntactic element is not (arr, n-1), it is multiply(arr, n-1).
A parameter is kind of like a "hole" that you leave in a function definition. Parameters allow you to make functions re-usable in different contexts.
For example, a function like this:
function doubleTheValueSix() {
return 2 * 6;
}
is not very useful because it can be used for only one very specific thing. However, we can make it more useful by parameterizing it:
function doubleAnyArbitraryValue(n) {
return 2 * n;
}
is much more useful. Here, n is called the parameter and (n) is called the parameter List. In this case, there is only one parameter in the parameter list, but there can be arbitrary many, including – as we have seen above – zero.
An argument is what you pass to a function call to "fill in" the "hole" left by the parameter in the function definition.
So, in this code here:
doubleAnyArbitraryValue(42)
The literal 42 is the argument which gets bound to the parameter n inside the function body of doubleAnyArbitraryValue. In other words, everywhere n appears in the function body, it gets replaced with 42.
So, in this case, 42 is the argument and (42) is the argument list.
What this means in your particular code snippet is the following:
Look up the name multiply in the local scope. It could be a function defined in the local scope (or in an enclosing scope), a const, a let, or a var defined in the local scope (or in an enclosing scope).
Call the object you found in step #1, passing the result of evaluating the expressions in the argument list as arguments:
Evaluate the expression arr (which essentially means: look up the name arr in the local scope; it could be a const, a let, or a var defined in the local scope (or in an enclosing scope)).
Evaluate the expression n-1:
Look up the name n in the local scope; it could be a const, a let, or a var defined in the local scope (or in an enclosing scope).
Apply the Binary Arithmetic Subtraction Operator - to the result of step 2.1.1 and the Numeric Literal 1.
You can find the details about how function calls work in subsection 13.3.6 Function Calls of the ECMAScript Language Specification. (Note, the version I linked to is the Living Document which always shows the current state of the next release, but that doesn't matter in this case – how function calls work fundamentally hasn't changed since ECMAScript was still called LiveScript in 1995 and even before that when it was still called Mocha.)
This question already has answers here:
What is the (function() { } )() construct in JavaScript?
(28 answers)
Closed 6 years ago.
from MDN, just wondering why the () around the function, why the extra () after it, and why the var b inside the function doesn't replace the value of the first var b, given it doesn't use the keyword let, which would keep b local to that function, thanks
var a = 1;
var b = 2;
(function() {
var b = 3;
a += b;
})();
a; // 4
b; // 2
When you write var b inside a function, the var keyword makes it a local variable. So, var b inside the function is a local variable and var b at the top which is outside the function is in global scope. You can read more about scoping in MDN. Also, the () after the function is called immediate function invocation which means that the function is given a call soon after it is defined. Also, since a inside the function has no var before its declaration, it will take the global a which is 1 and add 3, local variable b's value it.
The function is simply called immediately. That’s what the last parentheses are for. The extra parentheses around the function declaration are because
function() {
var b = 3;
a += b;
}();
would create a syntax error as the function keyword would not be interpreted as an expression here.
and why the var b inside the function doesn't replace the value of the first var b, given it doesn't use the keyword let, which would keep b local to that function,
You may have heard that the special thing about let is that it is block-scoped. That’s true. But var has always been scoped to the function and since the second var b is inside its own function it’s scoped to that function and does not affect the b from the top scope here.
The template
(function(){})();
Is a template of an anonymous function.
To explain it, let's create a function x() that alerts 'hello':
function x() {
alert('hello');
}
To call x, we will:
x();
Now, it's clear that if we replace an object's name with it's value, the statememt will stay the same (take for example var k = 5; alert(k); alert(5) - the two alerts are the same because variable's name was replaced with it's value).
In our case, x's value is:
function () {
alert('hello');
}
So if we replace x with it's value in the statement x(); ->
(function () {
alert('hello');
})();
And that's the source of the syntax. The result of that will be an immediate call to the specified function. Of course, this syntax works also for functions with parameters and functions with return types.
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.
My question is really more about scope in JavaScript, rather then closures.
Let's take the following code:
var f = function () {
var n = 0;
return function () {
return n++;
};
}();
console.log(f());
console.log(f());
The above code outputs:
0
1
As you can see from the above code, f (self-invoked) returns a function, creating a closure of n.
So, it works with an anonymous function; thus, I then tried it with a named function:
var f2 = function () {
return n++;
};
var f = function () {
var n = 0;
return f2;
}();
console.log(f2()); // <= [n is not defined]
The above code doesn't work, with the error n is not defined. I assume that this is a scoping issue; but I cannot figure why exactly;
Why is it that the scope is the same with an anonymous, inner function but does not work with a named, outer function?
Also, in the second example, am I creating a closure?
The closure is created in the first example because the code in the anonymous function uses a local variable that is declared outside of the anonymous function.
In the second example the scope of the n variable in the function f2 is already decided when the function is declared. Creating a local variable with the same name doesn't change the meaning of the function, and using the function inside another function doesn't change it's scope. Thus, the function doesn't use the local variable.
scoping in javascript is lexical http://en.wikipedia.org/wiki/Scope_%28programming%29#Static_scoping_.28also_known_as_lexical_scoping.29
There is no way for f2 to figure out where it should take variable n.
In first example anonymous function is inside function f, in second - outside (f2 instead of anonymous). So, f2 cannot access variable n, because it is in another scope and inaccessible (invisible). Try put f2 declaration inside f.
In your second example, you are not creating a closure, you are simply returning a global variable. f2 is not being closed over because it was declared in a more general (in this case, global) scope, and n is declared in a more specific scope. Closure is possible down the scope chain "funnel," not up, and is only effective when all related entities are defined in the same scope.
We could rewrite your second example to make it work with a named function:
var f = function() {
var n = 0;
var f2 = function() {
return n++;
};
return f2;
}();
console.log(f());
console.log(f());
This would output, 0 and 1 as your first example did.
As the other answers have stated, its not about the function being named or anonymous, its about scope of n and f2. Since you declared f2 outside of f in your example, it had no access to the variable n declared inside the scope of f.