Что делает этот код Node.js, который, по-видимому, заменяет реализацию функции внутри той же самой функции? - PullRequest
4 голосов
/ 07 февраля 2020

Я пытаюсь отладить огромную кучу Node.js кода, и следующее выглядит для меня безумно (из-за моего опыта в C ++ и C#). Есть много функций, которые выглядят так:

function _builderUtil() {
    const data = require("builder-util");
    _builderUtil = function () {
        return data;
    };
    return data;
}

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

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

Какова цель этой внутренней функции (которая выглядит анонимно)? Что делает этот код и как он называется в Node.js, поэтому я знаю, что искать?

1 Ответ

3 голосов
/ 07 февраля 2020

Или, может быть, это заменяет реализацию внешней функции.

Вот что она делает. При первом вызове _builderUtil он вызывает require и сохраняет результат в локальной константе data. Затем она перезаписывает функцию, которая сделала это, функцией, которая просто возвращает эту data константу. (Константа data сохраняется, потому что внутренняя функция закрывается над ней.)

По сути, она лениво загружает данные через require, а затем возвращает те же данные каждый раз, когда вы вызываете их после загрузки.

Как отмечает CertainPerformance в комментарии, это не нужно. Модульная система Node.js поддерживает кэш загруженных модулей, поэтому вместо вызова _builderUtil было бы достаточно просто использовать require("builder-util") каждый раз, когда вам нужны данные.

Но вернемся к тому, как он работает и игнорирует детали require:

Изначально у вас в памяти есть что-то вроде этого:

                  +−−−−−−−−−−−−+
_builderUtil−−−−−>| (function) |
                  +−−−−−−−−−−−−+
                  | [code]     |
                  +−−−−−−−−−−−−+

При первом вызове это объект лексической среды создается для местных жителей для вызова функции. Внутри этого объекта среды есть константа data, которая инициализируется результатом вызова require (предположительно, некоторые данные). Сразу после вызова const data = require("builder-util"); и до _builderUtil = после него вы получите:

                  +−−−−−−−−−−−−+
_builderUtil−−−−−>| (function) |
                  +−−−−−−−−−−−−+
                  | [code]     |
                  +−−−−−−−−−−−−+

                  +−−−−−−−−−−−−−−+
                  | (env object) |
                  +−−−−−−−−−−−−−−+      +−−−−−−−−−−−−−+
                  | data         |−−−−−>| (some data) |
                  +−−−−−−−−−−−−−−+      +−−−−−−−−−−−−−+

Затем функция перезаписывает _builderUtil новой функцией, которая просто возвращает data. Функции имеют ссылку на объект среды, в котором они были созданы, поэтому после завершения вызова вы получите следующее:

                  +−−−−−−−−−−−−+
                  | (function) |  (the old function, ready to be garbage−collected)
                  +−−−−−−−−−−−−+
                  | [code]     |
                  +−−−−−−−−−−−−+

                         +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
                         |                               |
                         v                               |
                  +−−−−−−−−−−−−−−+                       |
                  | (env object) |                       |
                  +−−−−−−−−−−−−−−+      +−−−−−−−−−−−−−+  |
                  | data         |−−−−−>| (some data) |  |
                  +−−−−−−−−−−−−−−+      +−−−−−−−−−−−−−+  |
                                                         |
                  +−−−−−−−−−−−−−−−+                      |
_builderUtil−−−−−>|   (function)  |                      |
                  +−−−−−−−−−−−−−−−+                      |
                  | [environment] |−−−−−−−−−−−−−−−−−−−−−−+
                  | [code]        |
                  +−−−−−−−−−−−−−−−+

В конечном итоге происходит сборка мусора, и у вас просто

                         +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
                         |                               |
                         v                               |
                  +−−−−−−−−−−−−−−+                       |
                  | (env object) |                       |
                  +−−−−−−−−−−−−−−+      +−−−−−−−−−−−−−+  |
                  | data         |−−−−−>| (some data) |  |
                  +−−−−−−−−−−−−−−+      +−−−−−−−−−−−−−+  |
                                                         |
                  +−−−−−−−−−−−−−−−+                      |
_builderUtil−−−−−>|   (function)  |                      |
                  +−−−−−−−−−−−−−−−+                      |
                  | [environment] |−−−−−−−−−−−−−−−−−−−−−−+
                  | [code]        |
                  +−−−−−−−−−−−−−−−+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...