问题
I'm studying from this site and came upon this question and answer:
Write a sum method which will work properly when invoked using either syntax below.
console.log(sum(2,3)); // Outputs 5
console.log(sum(2)(3)); // Outputs 5
//answer
function sum(x) {
if (arguments.length == 2) {
return arguments[0] + arguments[1];
} else {
return function(y) { return x + y; };
}
}
I understand the code in the if statement, but not in the else statement because it's simply returning a function. That function isn't called with a '()', so given the 2nd scenario of console.log(sum(2)(3));
I don't see why it will return 5. I can only see that it will return function(3) {return 2 + 3}
which should throw an error.
回答1:
The else statement is returning a function with the x value encapsulated from the first call
To explain it will break it down a little
var fresult = sum(3);
// right now fresult is a function that will add 3
// to the variable you call fresult with
// basically function(y){ return 3 + y; }
var result = fresult(4);
//result is 7
console.log(result);
Think of it like the value of x is being captured by the function that is being returned, which you can then call
This encapsulation is created by the closure created in the anonymous function in the else's return statement
To learn more about closures take a look at this MDN Article about them, they will be able to explain it a lot better than I could.
They actually have an example that is very similar to yours, where they try to explain the concept as being similar to a factory:
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
Article Says :
In this example, we have defined a function makeAdder(x) which takes a single argument x and returns a new function. The function it returns takes a single argument y, and returns the sum of x and y.
In essence, makeAdder is a function factory — it creates functions which can add a specific value to their argument. In the above example we use our function factory to create two new functions — one that adds 5 to its argument, and one that adds 10.
add5 and add10 are both closures. They share the same function body definition, but store different environments. In add5's environment, x is 5. As far as add10 is concerned, x is 10.
So if you are used to a more traditional programming language some use cases that you would have for private variables would be the same as capturing variables value's in a closure
回答2:
sum(2) = function (y){ return 2 + y }
You are calling that function with (3)
回答3:
You can store a function in a variable.
Basic idea is
var foo = function(y) {
return y
};
So when we look at
console.log(sum(2)(3));
can be written as
var part1 = sum(2); //aka part1 = function(y) { return 2 + y; };
var ans = part1(3);
console.log(ans);
回答4:
else
part is an anonymous function that accepts one
argument.
In case sum(2)(3)
It goes into else loop, where x = 2
since its called as sum(2)
, whereas (3)
is an anonymous function with no name.
hence,
return function(y) { return x + y; };
becomes
return function(3) { return 2 + 3; };
回答5:
Javascript is a bit different from many languages. Functions can be passed around as variables. In your case, what's happening is much easier to see when broken down into the steps that actually occur.
First, since sum(2)
has only one parameter, we go to the else
block, which you already know. What's happening there is that we are returning a function, substituting x
for the variable that was passed into sum(x)
. So basically, what's being returned is a function that returns 2 + y
. This is what it would look like if we wanted to write it out on its own:
function(y) {
return 2 + y;
}
The second set of parenthesis in sum(2)(3)
is basically saying "call the function that was returned by sum(2)
and send it the parameter 3
.
Here's basically an expanded version of the whole operation:
function sum(x) {
if (arguments.length == 2) {
return arguments[0] + arguments[1];
} else {
return function(y) { return x + y; };
}
}
var addTwo = sum(2);
console.log(addTwo(3));
The short version basically just skips creating a separate variable for the result of sum(2)
and just immediately calls the new function instead.
来源:https://stackoverflow.com/questions/36273538/how-does-return-work-in-javascript-without-a-function-being-invoked