0

我有一个用于客户端站点的 javascript 库,如下所示:

  <script src="foo.js"></script>
  <div id="mydiv"></div>
  <script>
    (function() {
        foo(document.getElementById("mydiv");
    })();
  </script>

即 foo.js 导出一个函数(“foo”),该函数假定获取一个 DOM 元素作为参数。

我想将 foo.js 拆分为几个不同的“模块”(逻辑部分),为此我正在查看BroserifyrequireJS。问题是,如果 browserify(据我所知,requireJS)不导出任何 foo 的顶级函数,所以我无法从 html 文件中访问“foo”函数,如上所示。似乎使用 browserify 我可以在构建最终 js 时使用-r选项:

browserify -r ./foo.js > bundle.js 

这将创建一个可以在客户端站点中使用的全局要求。不过,我对这个解决方案不太满意,因为它污染了全局空间,而且我的脚本旨在嵌入其他站点(可能有冲突的require)。我在这里运气不好?我错过了什么吗?我想我所需要的只是一种方法来加入不同的 js 源文件以便于开发并且只导入一个最终的 javascript。有没有更好的解决方案适合我的需求?

米;

4

1 回答 1

1

如果您将脚本拆分为多个文件,那么这些文件需要能够相互通信。两个不同的脚本文件相互通信的唯一方法是通过全局命名空间,这是它们唯一的共同点。

我对 Broserify 不熟悉,但在 requirejs 的情况下,脚本利用全局命名空间进行通信的方式是,它们在执行时都会将自己的引用传递给全局“require”或全局“define”函数。requirejs 本身会在内部跟踪脚本,因此它们不必对全局命名空间产生任何其他影响——但 requirejs 已经通过创建名称“require”和“define”来做到这一点。

在任何情况下,您的脚本总是可以通过分配一个未声明的变量来影响全局命名空间,该变量将在全局对象中创建一个属性:

foo = function() {}; // creates global name as long as no other 'foo' is in scope
// or
window.foo = function() {}; // as long as no other 'window' variable is in scope

无论您的脚本如何加载,您都可以随时执行此操作。其他脚本现在可以通过全局名称“foo”进行交互,方法是读取和/或分配此全局名称的属性。

foo.prop1 = 'val1';
if(foo.preExistingProp) {
    // do something
}

像 requirejs 这样的库的主要目的是,当您开发脚本时,相对依赖关系可能会发生变化。您可以想象脚本 A 需要脚本 B 和 C,而脚本 B 需要脚本 D。现在脚本可以有效加载多个命令。其中一些是:

D -> B -> C -> A
C -> D -> B -> A
D -> C -> B -> A

requirejs 采用依赖并将其转换为动态的线性加载顺序。当这棵树发生变化时,它会重新计算加载顺序以确保它保持有效。

如果您需要这种功能,我鼓励您使用这样的库,尽管您对全局命名空间的关注是适当的。如果您只需要一个您自己管理的简单线性加载顺序,那么您可以让您的脚本直接与我上面概述的全局“foo”名称交互。

于 2013-10-21T01:32:57.910 回答