26

我目前正在维护大量的 JS 文件,并且依赖问题越来越严重。现在我将每个函数都放在一个单独的文件中,并且我手动维护一个数据库来计算函数之间的依赖关系。

这我想自动化。例如,如果我有函数 f

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

在另一个函数 g 中引用

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

我希望能够检测到 g 正在引用 f。

我该怎么做?我从哪说起呢?我是否需要实际编写一个编译器,或者我可以调整 Spidermonkey 吗?其他人已经这样做了吗?

非常感谢任何让我开始的指示

谢谢多克

4

6 回答 6

18

虽然理论上您可以编写一个静态分析工具来检测其他文件中定义的全局变量的使用,例如使用MyObject,但您无法实际跟踪prototype扩展方法的使用。

JavaScript 是一种动态类型的语言,因此任何工具都没有实际的方法可以知道a,如果从函数中传递出来g,它就是一个Array,因此如果f()在它上面调用它,就会存在依赖关系。它只会在运行时确定哪些变量持有哪些类型,因此要找出你需要一个解释器并且你已经让自己成为一个图灵完备的问题。

更不用说 JavaScript 的其他动态方面完全无视静态分析,例如通过方括号表示法获取属性、dreadedeval或超时字符串或事件处理程序属性。

我认为这真的是一个非首发。您可能最好手动跟踪依赖项,但通过将相关功能分组到模块中来简化它,这将是您的依赖项跟踪的基本单元。好的,您将引入更多技术上需要的功能,但希望不要太多。

为每个模块命名也是一个好主意,因此每个调用的去向非常清楚,从而可以轻松地手动控制依赖关系(例如,通过// uses: ThisModule, ThatModule顶部的注释)。

由于内置原型的扩展很难跟踪,因此将它们保持在最低限度。扩展例如。Array在尚未拥有它们的浏览器上包含 ECMAScript 第五版方法(如indexOf)是一件好事,作为所有脚本都将使用的基本修复。向现有原型添加全新的任意功能是值得怀疑的。

于 2010-07-08T10:40:53.927 回答
10

您是否尝试过使用RequireJSLabJS 之类的依赖管理器?我注意到没有人在这个线程中提到它们。

http://requirejs.org/docs/start.html

在 main.js 中,您可以使用 require() 来加载您需要运行的任何其他脚本:

require(["helper/util"], function(util) {
    //This function is called when scripts/helper/util.js is loaded.
    //If util.js calls define(), then this function is not fired until
    //util's dependencies have loaded, and the util argument will hold
    //the module value for "helper/util".
});

您也可以嵌套这些依赖项,因此 helper/util 可以在其内部需要一些其他文件。

于 2012-02-21T22:10:37.233 回答
8

正如@bobince 已经建议的那样,对 JavaScript 程序进行静态分析是一个几乎不可能破解的问题。Google Closure 编译器在一定程度上做到了这一点,但它也依赖于JSDoc注释的外部帮助。

我有一个类似的问题,即在以前的项目中查找 JS 文件应该连接的顺序,并且由于有大量 JS 文件,手动更新包含顺序似乎太乏味了。相反,为了我的目的,我坚持使用某些构成依赖项的约定,并基于此并使用简单的正则表达式:) 我能够生成正确的包含顺序。

该解决方案使用拓扑排序算法生成依赖关系图,然后按照文件应包含的顺序列出文件以满足所有依赖关系。由于每个文件基本上都是使用MooTools语法的伪类,因此对于我的情况,只有 3 种方式可以创建依赖项。

  1. 当一个类扩展了其他类时。
  2. 当一个类实现了其他一些类。
  3. new当一个类使用关键字实例化某个其他类的对象时。

这是一个简单的,对于通用用途来说绝对是一个破碎的解决方案,但它对我很有帮助。如果您对解决方案感兴趣,可以在此处查看代码- 它使用 Ruby。

如果您的依赖项更复杂,那么也许您可以使用注释和一些本地语法手动列出每个 JS 文件本身中的依赖项,例如:

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

然后读取每个 JS 文件,解析出所需的注释,并构建一个依赖图,它将为您提供所需的包含顺序。

于 2010-07-09T02:51:01.347 回答
5

如果有一个工具可以自动为您检测这些依赖项并选择它们的加载方式,那就太好了。不过,今天最好的解决方案有点粗糙。我为我想要添加到列表中的特定需求创建了一个依赖管理器(金字塔依赖管理器)。它具有一些关键功能,可以解决一些独特的用例。

  1. 处理其他文件(包括为视图插入 html...是的,您可以在开发过程中分离视图)
  2. 当您准备好发布时,在 javascript 中为您组合文件(无需安装外部工具)
  3. 对所有 html 页面都有一个通用的包含。当依赖项被添加、删除、重命名等时,您只需更新一个文件

一些示例代码来展示它在开发过程中是如何工作的。

文件:dependencyLoader.js

//Set up file dependencies
Pyramid.newDependency({
    name: 'standard',
    files: [
    'standardResources/jquery.1.6.1.min.js'
    ]
});

Pyramid.newDependency({
name:'lookAndFeel',
files: [
    'styles.css',
    'customStyles.css',
    'applyStyles.js'
    ]
});

Pyramid.newDependency({
name:'main',
files: [
    'createNamespace.js',
    'views/buttonView.view', //contains just html code for a jquery.tmpl template
    'models/person.js',
    'init.js'
    ],
    dependencies: ['standard','lookAndFeel']
});

html 文件

<head>
    <script src="standardResources/pyramid-1.0.1.js"></script>
    <script src="dependencyLoader.js"></script>
    <script type="text/javascript">
        Pyramid.load('main');
    </script>
</head>

它确实需要您维护一个文件来管理依赖项。我正在考虑创建一个程序,该程序可以根据头文件中的包含自动为您生成加载程序文件,但由于它处理许多不同类型的依赖项,因此将它们维护在一个文件中实际上可能会更好。

于 2011-08-16T10:44:10.480 回答
1

JSAnalyse 使用静态代码分析来检测 javascript 文件之间的依赖关系:http: //jsanalysis.codeplex.com/

例如,它还允许您定义允许的依赖项并确保它在构建期间。当然,它不能检测所有依赖项,因为 javascript 是动态解释语言,它不是类型安全的,就像已经提到的那样。但它至少让您了解您的 javascript 依赖关系图并帮助您控制它。

于 2011-11-29T19:20:48.843 回答
0

我写了一个工具来做这样的事情:http: //github.com/damonsmith/js-class-loader

如果你有一个 java webapp 并且你用 java 风格来构建你的 JS 代码,这将是最有用的。如果您这样做,它可以检测您的所有代码依赖项并将它们捆绑在一起,同时支持运行时和解析时依赖项。

于 2013-10-03T05:27:03.823 回答