Функции более высокого порядка в Javascript

Я читаю "Красноречивый JavaScript" (Новая версия), и я дошел до части функций более высокого порядка, и я смущен тем, что происходит в следующий код.

function noisy(f) {
  return function(arg) {
    console.log("calling with", arg);
    var val = f(arg);
    console.log("called with", arg, "- got", val);
    return val;
  };
}
noisy(Boolean)(0);
// → calling with 0
// → called with 0 - got false
  • Почему вызов функции звучит так? Является ли (Boolean) литой? Кастинг для чего? возвращаемое значение? или аргумент? почему not (Boolean) шумный (0), если его возвращаемое значение. Или шумный ((Boolean) 0), если аргумент является тем, который был выбран.

    noisy(Boolean)(0)
    
  • Что происходит в этой строке? Где f() даже определено?

    var val = f(arg);
    

Ответы

Ответ 1

  • Boolean - это функция. Это функция, которую вы вызываете косвенно через noisy. Я немного сбиваю с толку, потому что это похоже на имя типа. Но в JavaScript те изначально запертые вещи (Boolean, Number, String и т.д.) Являются функциями. Когда вы вызываете Boolean ( без с помощью new), он пытается преобразовать аргумент, который вы ему дали, в примитивное значение Boolean и возвращает результат. (См. §15.6.1 в спецификации.)

  • f - это имя аргумента в функции noisy.

Функции в JavaScript - это объекты первого класса. Вы можете передать их в другие функции в качестве аргументов, как и любой другой объект.

Когда вы делаете

noisy(Boolean)(0)

Происходит две вещи. Во-первых:

// (In effect, we're not really creating a variable...)
var x = noisy(Boolean);

Это дает нам функцию, которая при вызове вызовет Boolean с аргументом, который мы даем, а также выполняем те операторы console.log. Это функция, которую вы видите созданной в noisy (return function(arg)...);

Тогда мы называем эту функцию:

x(0);

И это, когда вы видите вывод консоли. Поскольку Boolean(0) - false, вы видите Boolean возвращаемое это значение.

Здесь гораздо более простой пример:

function foo(bar) {
    bar();
}
function testing() {
    alert("testing got called");
}
foo(testing);

Там, я передаю функцию testing в foo. Имя аргумента, которое я использую для этого в foo, равно bar. Строка bar(); вызывает функцию.

Ответ 2

Функция без() - это действительная функция. Функция с() является вызовом функции. Также имейте в виду, что JavaScript является свободно типизированным языком, поэтому вы не объявляете типы переменных. Я добавил несколько комментариев к вашему примеру, чтобы попытаться помочь.

// We define a function named noisy that takes in an argument named f. We are expecting f to be a function but this isn't enforced till the interpreter throws an error. 
function noisy(f) {
// Noisy returns a single item, an anonymous function. That anonymous function takes in an argument named arg
  return function(arg) {
    console.log("calling with", arg);
// Our anonymous function then takes f (It can use f because its defined inside noisy, see closures for more details) and invokes it with the argument arg and stores the result in a variable named val. 
    var val = f(arg);
    console.log("called with", arg, "- got", val);
// It now returns val
    return val;
  };
}

Итак, тогда шумный (булевский) (0) работает следующим образом

f - функция Boolean

noisy возвращает такую ​​функцию

function(arg) {
  var val = Boolean(arg);
  return val;
}

Итак, теперь мы имеем

наша возвращенная функция (0)

который выполняет как нормальный, чтобы стать

function(0) {
  var val = Boolean(0); // false
  return val;
}

Ответ 3

Я относительно новичок в JS, и я просто читал Eloquent Javascript, и мне стало легче понять, как только я понял вызов функции (отвечая на вашу точку 1):

noisy(Boolean)(0);

noisy(Boolean) создает новую функцию, а (0) - после нее, потому что она передается в качестве аргумента в эту новую функцию. Если вы вернетесь к примеру больше:

function greaterThan(n) {
  return function(m) { return m > n; };
}
var greaterThan10 = greaterThan(10);
console.log(greaterThan10(11));

Его также можно было бы вызвать следующим образом:

greaterThan(10)(11);

Надеюсь, что это разъяснит ваш первый вопрос о том, почему он так называется.

Во второй вопрос. f in:

var val = f(arg);

- это функция Boolean, которая была передана в noisy, когда был введен noisy(Boolean). Затем он использовался как аргумент в шумной функции. Я также не понимал, что Boolean может быть самой функцией, а не только типом данных. Как говорили другие, он преобразует аргумент, который вы передали ему в логическое значение, и возвращает результат.

Следовательно, val становится Boolean(arg), который становится Boolean(0), который вычисляется до false. Если вы попробуете позвонить noisy(Boolean)(1);, вы увидите, что он возвращает true. console.log("called with", arg, "- got", val); просто записывает аргумент (0 в этом случае) и результат его оценки (false).

Фактически, он изменил логическую функцию на единицу, которая регистрирует аргумент и результат, а также возвращает результат.

Надеюсь, это поможет. Просто написать это помогло мне понять.

Ответ 4

Если у вас все еще есть проблемы с этим, вот как я это понимаю (это также дало мне головную боль..)

function noisy(f) {
    return function(arg) {
        console.log("calling with", arg);
        var val = f(arg);
        console.log("called with", arg, "- got", val);
        return val;
    };
}

noisy(Boolean)(0)

Функция является просто регулярным значением. Предыдущее предложение является ключевым для понимания того, что происходит здесь.

Наша шумная (f) функция является значением. Это то, что он возвращает.

noisy (f) возвращает функцию, которая принимает аргумент (arg).

шум (f) также принимает аргумент (f). Внутренние функции (функции, вызываемые изнутри функций) имеют доступ к переменным и аргументам, которые были переданы внешней функции.

Мы вызываем нашу внешнюю функцию и передаем ей аргумент Boolean. Наша внешняя функция возвращает свою внутреннюю функцию, которая принимает аргумент (0). Понимая вышеизложенное, должно стать ясно, что шумный (булевый (0)) просто передаст аргумент нашей внешней функции, не передавая ничего внутренней функции, возвращаемой нашей внешней функцией.

Это так просто. Теперь, когда мы это понимаем, трудно поверить, что это дало нам такую ​​головную боль, чтобы начать с... */`