Как обрабатываются параметры при передаче функций в Javascript?
В http://eloquentjavascript.net/1st_edition/chapter6.html есть следующий пример:
function negate(func) {
return function(x) {
return !func(x);
};
}
var isNotNaN = negate(isNaN);
alert(isNotNaN(NaN));
Зная только базовый Javascript и императивное программирование, я озадачен этим стилем программирования. Может ли кто-нибудь помочь мне понять, что происходит во время выполнения.
Я прошел через код и проверил переменные и обнаружил, что значение x
является NaN
, Откуда он знает, что аргумент isNaN
должен быть передан в качестве аргумента x
анонимной функции? Во-первых, почему фактический параметр NaN из isNotNaN
стать аргументом isNaN
(т.е. пока isNaN
ожидает аргумент, почему он берет его из аргумента isNotNaN
)?
3 ответа
Лучший способ понять это - увидеть, что эти вещи на самом деле равны. Обратите внимание, как func
становится пройденным isNaN
функция.
function negate(func) {
return function(x) {
return !func(x);
};
}
var isNotNaN = negate(isNaN);
/*
isNotNaN = function(x){
return !isNaN(x)
}
*/
alert(isNotNaN(NaN));
Заметить, что negate
оба принимают функцию в качестве аргумента и возвращают функцию. Возвращенная функция вызовет функцию аргумента, отрицая возвращаемое значение. Таким образом, isNotNaN
это функция. Когда он вызывается, он вызывает функцию, первоначально переданную в negate
, в этом случае isNaN
, Как бы вы ни назвали isNotNaN
с будет передан isNaN
,
По сути, вы настраиваете функцию с другой функцией. Это может быть легче увидеть на более простом примере (без функции аргумента):
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
Теперь сделайте еще один шаг вперед и представьте, что вы передали функцию в addX
вместо значения.
Кстати, это называется карри.
Это потому, что вы установили это:
var isNotNaN = negate(isNaN);
И при вызове isNotNaN(x) это так же, как вы вызываете negate(isNaN)(x). Вы также можете использовать именованную функцию вместо анонимной, поэтому мы говорим:
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.