ilyachalov (ilyachalov) wrote,
ilyachalov
ilyachalov

Categories:

Учебник по JavaScript: ч.1: new Function, планирование, декораторы

Продолжаю читать шестой раздел («Продвинутая работа с функциями») первой части («Язык программирования JavaScript») учебника по JavaScript.

https://learn.javascript.ru

Часть 1. Язык программирования JavaScript (в т.ч. 93 подраздела)

Разделы:

6. Продвинутая работа с функциями (11 подразделов)

6.7 Синтаксис "new Function"
6.8 Планирование: setTimeout и setInterval
6.9 Декораторы и переадресация вызова, call/apply

В подразделе 6.7 речь идет о еще одном способе создать новую функцию (кроме рассмотренных ранее обычного объявления функции (по-английски «Function Declaration»), с помощью функционального выражения (по-английски «Function Expression») и функций-стрелок (по-английски «arrow functions»)). Синтаксис «new Function» позволяет создать функцию из любой строки (в этой строке должен содержаться текст функции). В функции, созданной этим способом, не сохраняется ссылка на лексическое окружение, то есть она не является замыканием. Такая функция «видит» только глобальное лексическое окружение (имеет доступ только к глобальным переменным). Это сделано, чтобы избежать проблем в работе минификатора, специальной программы, уменьшающей размер кода. В википедии есть статья о минификации:

https://ru.wikipedia.org/wiki/Минификация_(программирование)

В подразделе 6.8 рассказано о том, как можно вызвать функцию не в данный момент, а через заданый интервал времени. Это можно делать с помощью функций setTimeout и setInterval (первая запускает указанную функцию один раз через заданный интервал времени, а вторая — запускает указанную функцию много раз через заданный интервал времени). Эти функции не входят в спецификацию языка JavaScript, но на практике реализованы во всех современных браузерах (потому что эти функции входят в стандарт HTML) и часто используются. Отмена запланированных ранее запусков функций производится с помощью функций clearTimeout и clearInterval.

В подразделе 6.9 рассказано про декораторы. Декораторы — это функции, которые с помощью функций-оберток (по-английски «wrapper») дают указанным функциям новые способности (новую функциональность). Пример из первой задачи к этому подразделу:

// некая функция для примера, к ней мы будем применять декоратор
function work(a, b) {
    alert( a + b );
}

// применение декоратора spy к функции work
work = spy(work);

// тестовые вызовы функции work
work(1, 2); // 3
work(4, 5); // 9

// выведем на экран массивы параметров вызовов функции work
for (let args of work.calls) {
    alert( 'call:' + args.join() ); // "call:1,2", "call:4,5"
}

Текста функции-декоратора spy здесь нет, так как в задаче ученику текст этой функции предлагается написать. Но я взял этот пример, чтобы показать принцип работы декоратора.

После применения декоратора spy к функции work у последней появляются новые способности. Теперь при каждом запуске функции work параметры, с которыми был выполнен запуск, сохраняются в массиве параметров, который в свою очередь сохраняется в массиве work.calls.

Декоратор назван spy, потому что новая функциональность, которую он добавляет к заданной функции, в данном случае позволяет как бы шпионить за вызовами этой функции.

Но, в принципе, декораторы могут добавлять функциям очень разнообразные способности. Например, в данном подразделе учебника работа декоратора рассмотрена на примере декоратора, который добавляет заданной функции способности кэширования результатов ее работы. Что это такое? Если работа функции занимает очень много времени или оказывает слишком большую нагрузку на процессор, и при этом для одного и того же набора входящих параметров эта функция возвращает один и тот же результат, то было бы уместно запоминать результаты работы этой функции в некой таблице, чтобы при повторном вызове этой функции с тем же набором входящих параметров мгновенно взять результат ее работы из таблицы. Таким образом, при повторных вызовах такой функции с теми же входящими параметрами убыстряется работа программы и уменьшается нагрузка на процессор.

Идея и реализация кэширования результатов работы функций мне очень понравилась. В качестве таблицы с результатами работы функции взято отображение map, про которое в учебнике уже рассказывалось ранее. При первом вызове функции результат ее работы помещается в отображение map с ключом, составленным из входящих параметров вызова функции. При повторных вызовах функции результат ее работы сначала ищем в отображении по входящим параметрам вызова функции и если находим, то возвращаем в качестве результата работы текущего вызова этой функции. Если не находим, то запускаем функцию, записываем результат ее работы в отображение и возвращаем этот результат.

Принцип реализации простейшей функции-декоратора можно увидеть в следующем коде:

function funcDecorator(func) { // функция-декоратор

    // ... придаём функции wrapper новую функциональность...

    function wrapper(x) {      // функция-обертка
    
        // ... придаём функции wrapper новую функциональность...
    
        return func(x);
    }

    // ... придаём функции wrapper новую функциональность...

    return wrapper;
}

Функция-декоратор funcDecorator получает функцию func, после чего конструирует внутри себя новую функцию-обертку wrapper, которая «клонирует» функцию func (получает те же входные параметры и выдает тот же результат, что и функция func), и улучшает ее, придавая ей новую функциональность (дополнительные способности).

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

При разработке кода функций-декораторов бывают очень нужны методы func.call и func.apply. Они позволяют выполнять вызов функции func с передачей в нее ссылки на контекст другой функции (this). Такие вызовы называют «перенаправлением вызова» или «переадресацией вызова» (по-английски «call forwarding»).

Еще в этом подразделе учебника рассказано про трюк, который называется «заимствованием метода». Например, можно позаимствовать методы массива для псевдомассивов.
Tags: Образование, Программирование
Subscribe

  • Сценарий фильма, который никогда не снимут

    Залпом прочитал набросок сценария художественного фильма, который в 2015-2016 годах написал в своем ЖЖ Григорий Циденков в десяти постах: 1.…

  • Непрощенный, 1992, кино

    Фильм очень понравился. Первый раз смотрел в 90-х, почти ничего не запомнил. Недавно пересмотрел дважды. После «долларовой трилогии» запустил на…

  • Вероятности в сериале «Менталист»

    В первой серии второго сезона сериала «Менталист» (серия называется «Искупление») сотрудники КБР обыскивают помещение, в котором полиция нашла убитую…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments