问题
In http://eloquentjavascript.net/1st_edition/chapter6.html, there is the following example:
function negate(func) {
return function(x) {
return !func(x);
};
}
var isNotNaN = negate(isNaN);
alert(isNotNaN(NaN));
Knowing only basic Javascript and imperative programming, I am stumped by this programming style. Can someone help me to understand what happens during runtime.
I stepped through the code and inspected variables and found that the value of x
is NaN
. How does it know that the argument to isNaN
should be passed as argument x
of the anonymous function? In the first place, why does the actual parameter NaN of isNotNaN
become the argument to isNaN
(ie while isNaN
expects an argument, why does it take it from the argument of isNotNaN
)?
回答1:
Best way to understand this might be with seeing what these things actually equal. Notice how func
becomes the passed isNaN
function.
function negate(func) {
return function(x) {
return !func(x);
};
}
var isNotNaN = negate(isNaN);
/*
isNotNaN = function(x){
return !isNaN(x)
}
*/
alert(isNotNaN(NaN));
回答2:
Notice that negate
both accepts a function as an argument and returns a function. The returned function will call the argument function, negating the return value. Thus, isNotNaN
is a function. When it is called, it will call the function originally passed into negate
, in this case isNaN
. Whatever you call isNotNaN
with will be passed to isNaN
.
In essence, you're configuring a function with another function. This might be easier to see with a simpler (no argument function) example:
function addX(x) {
return function(y) {
return x+y;
};
}
var add2 = addX(2);
console.log(add2(2)); // 4
var add3 = addX(3);
console.log(add3(7)); // 10
Now, take this one step further and imagine you passed a function into addX
instead of a value.
By the way, this is called currying.
回答3:
It is because you set this:
var isNotNaN = negate(isNaN);
And when calling isNotNaN(x)so it is like you call negate(isNaN)(x). You can also use a named function instead of the anonymous here so we say:
function negate(func) {
return xValue.call(this, x); //to be in the context of the xValue function
};
}
var isNotNaN = negate(isNaN);
alert(isNotNaN(NaN));
function xValue(x) {
return !func(x);
}
But then you have to take care about the context.
来源:https://stackoverflow.com/questions/32669993/how-are-parameters-handled-when-passing-functions-in-javascript