Как обрабатываются параметры при передаче функций в 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.
Другие вопросы по тегам