Управление зависимостью JavaScript

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

Это я хотел бы автоматизировать. Например, если у меня есть функция f

Array.prototype.f = function() {};

на который ссылаются в другой функции g

MyObject.g = function() {
    var a = new Array();
    a.f();
};

Я хочу смочь обнаружить, что g ссылается на f.

Как я иду об этом?С чего начать? Я должен на самом деле записать компилятор, или я могу настроить Spidermonkey, например? Кто-либо еще уже сделал это?

Любые указатели для запущения меня очень ценятся

Спасибо Dok

26
задан gblazex 8 July 2010 в 10:25
поделиться

2 ответа

Как уже предположил @bobince, выполнение статического анализа в программе JavaScript - это почти неразрешимая проблема. Компилятор Google Closure делает это в некоторой степени, но он также полагается на внешнюю помощь из комментариев JSDoc .

У меня была аналогичная проблема , заключающаяся в нахождении порядка, в котором файлы JS должны быть объединены в предыдущем проекте, и, поскольку файлов JS было много, обновление порядка включения вручную казалось слишком утомительным. Вместо этого я придерживался определенных соглашений о том, что представляет собой зависимость для моих целей, и, основываясь на этом и используя простое регулярное выражение :), я смог сгенерировать правильный порядок включения.

Решение использовало алгоритм топологической сортировки для создания графа зависимостей , который затем перечислял файлы в том порядке, в котором они должны быть включены, чтобы удовлетворить все зависимости. Поскольку каждый файл был в основном псевдоклассом, использующим синтаксис MooTools , для моей ситуации было только 3 способа создания зависимостей.

  1. Когда класс расширен каким-то другим классом.
  2. Когда класс Реализовал какой-то другой класс.
  3. Когда класс создает экземпляр объекта другого класса с помощью ключевого слова new .

Это было простое и определенно неработающее решение для общего использования, но оно мне пригодилось. Если вас интересует решение, вы можете увидеть код здесь - он написан на Ruby.

Если ваши зависимости более сложные, то, возможно, вы могли бы вручную перечислить зависимости в каждом файле JS, используя комментарии и некоторый собственный синтаксис, например:

// requires: Array
// requires: view/TabPanel
// requires: view/TabBar

Затем прочитайте каждый файл JS, проанализируйте требуемые комментарии и создайте график зависимостей, который даст вам нужный порядок включения.

8
ответ дан 28 November 2019 в 07:22
поделиться

Хотя теоретически можно написать инструмент статического анализа, который обнаруживает использование глобальных значений, определенных в других файлах, например, использование MyObject, вы не сможете реально отследить использование методов расширения prototype.

JavaScript - динамически-типизированный язык, поэтому нет практического способа для любого инструмента узнать, что a, переданный из функции g, является Array, и поэтому, если для него вызывается f(), существует зависимость. Какие переменные имеют типы, выясняется только во время выполнения, так что для выяснения этого вам понадобится интерпретатор, и вы создадите себе проблему, полную по Тьюрингу.

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

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

Также хорошей идеей будет задать пространство имен для каждого модуля, чтобы было ясно, куда идет каждый вызов, что облегчит контроль зависимостей вручную (например, с помощью // uses: ThisModule, ThatModule комментарием вверху).

Поскольку за расширениями встроенных прототипов следить сложнее, сведите их к минимуму. Расширение, например, Array для включения методов пятого издания ECMAScript (таких как indexOf) в браузерах, которые еще не имеют их, является хорошим решением в качестве базового исправления, которое будут использовать все скрипты. Добавление совершенно новой произвольной функциональности к существующим прототипам сомнительно.

18
ответ дан 28 November 2019 в 07:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: