>function greaterThan(n) {
> return function(m) { return m > n; };
>}
>var greaterThan10 = greaterThan(10);
>console.log(greaterThan10(11));
>// → true
Можно сделать функцию, меняющую другие функции.
>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
Можно даже делать функции, создающие новые типы управления потоком выполнения программы.
>function unless(test, then) {
> if (!test) then();
>}
>function repeat(times, body) {
> for (var i = 0; i < times; i++) body(i);
>}
>repeat(3, function(n) {
> unless(n % 2, function() {
> console.log(n, "is even");
> });
>});
>// → 0 is even
>// → 2 is even
Правила лексических областей видимости, которые мы обсуждали в главе 3, работают нам на пользу в таких случаях. В последнем примере переменная >n
– это аргумент внешней функции. Поскольку внутренняя функция живёт в окружении внешней, она может использовать >n
. Тела таких внутренних функций имеют доступ к переменным, окружающим их. Они могут играть роль блоков >{}
, используемых в обычных циклах и условных выражениях. Важное отличие в том, что переменные, объявленные внутри внутренних функций, не попадают в окружение внешней. И обычно это только к лучшему.
Функция >noisy
, объявленная ранее, которая передаёт свой аргумент в другую функцию, не совсем удобна.
>function noisy(f) {
> return function(arg) {
> console.log("calling with", arg);
> var val = f(arg);
> console.log("called with", arg, "- got", val);
> return val;
> };
>}
Если >f
принимает больше одного параметра, она получит только первый. Можно было бы добавить кучу аргументов к внутренней функции (>arg1
, >arg2
и т. д.) и передать все их в >f
, но ведь неизвестно, какого количества нам хватит. Кроме того, функция >f
не могла бы корректно работать с >arguments.length
. Так как мы всё время передавали бы одинаковое число аргументов, было бы неизвестно, сколько аргументов нам было задано изначально.
Для таких случаев у функций в JavaScript есть метод >apply
. Ему передают массив (или объект в виде массива) из аргументов, а он вызывает функцию с этими аргументами.
>function transparentWrapping(f) {
> return function() {
> return f.apply(null, arguments);
> };
>}
Данная функция бесполезна, но она демонстрирует интересующий нас шаблон – возвращаемая ею функция передаёт в >f
все полученные ею аргументы, но не более того. Происходит это при помощи передачи её собственных аргументов, хранящихся в объекте