Обратные вызовы и функции высшего порядка Javascript

Это проблема из главы 5 Eloquent JS http://eloquentjavascript.net/05_higher_order.html.

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)(12);
// → calling with 0
// → called with 0 - got false

Может кто-нибудь объяснить, как f(arg) имеет смысл? Я имею в виду, что он вызывает аргумент f для другого аргумента arg?? Я очень смущен.

Как насчет части, которая имеет return val; Почему это должно быть там? Когда я удаляю его, код по-прежнему работает так, как должен.

Наконец, кто-нибудь может объяснить интерпретацию кода построчно? Как передать логическое значение в примере?

Большое спасибо


person Yashar Feizi    schedule 20.02.2015    source источник


Ответы (3)


Следует помнить одно простое правило: вложенные функции в Javascript (например, функции, объявленные внутри других функций) имеют доступ ко всем переменным и аргументам своих родительских функций.

Когда noisy(f) вызывается и возвращает другую функцию, это создает замыкание в Javascript. Это означает, что даже несмотря на то, что noisy(f) завершил выполнение, его аргументы и любые локальные переменные все еще живы и могут использоваться внутренней функцией.

Итак, когда эта внутренняя функция затем вызывается, она имеет полный доступ к аргументу f из предыдущего выполнения своей родительской функции. Вот справочник MDN по замыканиям, который, возможно, стоит прочитать и ответ StackOverflow, объясняющий закрытие.

Итак, давайте шаг за шагом разберем, что делает ваш код:

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

// split up noisy(Boolean)(12); into two steps
var temp = noisy(Boolean);
temp(12);

Когда вызывается noisy(Boolean), это возвращает внутреннюю функцию, и для любого будущего вызова этой внутренней функции аргумент f устанавливается в функцию-конструктор Boolean.

Когда эта возвращаемая функция затем вызывается с собственным аргументом, как в temp(12) выше, она завершает выполнение Boolean(12) и возвращает это (чье значение будет true).

Рабочая демонстрация: http://jsfiddle.net/jfriend00/mkn839gu/

person jfriend00    schedule 20.02.2015
comment
@YasharFeizi - это ответило на ваш вопрос? Поскольку похоже, что вы, возможно, новичок в StackOverflow, знаете ли вы, что если вы получите ответ на свой вопрос, вам следует выбрать лучший ответ и щелкнуть зеленую галочку слева от ответа. Это сообщит сообществу, что на ваш вопрос был дан ответ, и принесет как вам, так и человеку, давшему ответ, несколько очков репутации. - person jfriend00; 27.02.2015

Основы:

noisy сопоставляет функцию с другой функцией, которая делает то же самое, что и исходная, но записывает входное и выходное значение (точнее, их строковые представления) в консоль.

  • Q1: Кажется, намерение состоит в том, чтобы улучшить конструкторы объектов с помощью простого средства регистрации, чтобы показать, какие аргументы инициализации создают какое состояние объекта. С этой целью noisy возвращает объект функции — исходную функцию, улучшенную выводом на консоль.

  • Q2: Расширенный конструктор Boolean вызывается без присвоения возвращаемого значения. Таким образом, для кода не имеет значения, возвращает ли расширенный конструктор значение или нет.

  • Q3: Boolean показывает, какие логические значения вы получаете для различных аргументов инициализации. Я предполагаю, что урок, который нужно усвоить, заключается в том, что числовое значение 0 дает вам false, все остальное true (последнее основано на предположении с моей стороны, но с noisy у вас есть инструмент для общей проверки для произвольных конструкторов и значений инициализации).

person collapsar    schedule 20.02.2015

просто:

аргумент в функции noisy (действующей как обертка) на самом деле просто

(Boolean());

(для ссылки на логический тип проверьте это).

Кроме того, вы используете 0 в качестве аргумента console.log во внутренней функции
и в качестве аргумента Boolean() (в var val).


Как насчет части, которая имеет return val; Почему это должно быть там? Когда я удаляю его, код по-прежнему работает так, как должен.

пока вы используете console.log, вы на самом деле не используете оператор return, но если бы вы это сделали

console.log(noisy(Boolean)(0))

вы можете увидеть оператор return после предыдущего console.logs

person maioman    schedule 27.04.2015