英文原文:JavaScript Modules 对于那些初学JavaScript、同时又正用它构建大型应用程序的开发者而言,必须面对的首要挑战是,该如何组织代码。尽管起初通过在
模块模式(The Module Pattern)解决此问题使用最为广泛的方法是模块模式(Module Pattern)。我尝试在下面解释一个基本示例,并谈论它的一些属性。对于各种不同方法更好的描述和梦幻般的运行,请参阅Ben Cherry的帖子——JavaScript Module Pattern: In-Depth(深入理解JavaScript模块模式)。 (function(lab49) { 上面的示例中,我们只使用一些来自语言本身的基本功能,就创建了曾在C#和Java等语言中见过的类似结构。 隔离(Isolation) 你会注意到这段代码包在一个立即调用的函数里(查看最后一行)。在浏览器中,默认情况下会在全局范围(global scope)级别上对JavaScript文件进行评估(evaluated),因此在我们在文件内声明的任何内容都是随处可用的。想象一下,如果在lib1.js中有句 命名空间(Namespacing) 在最后一行中,你会发现我们要么把 首个包含进来的文件会评估OR(逻辑或)语句,并发现左侧表达式为undefined(未定义)。由于undefined是虚假值(falsely value),因此OR语句会继续评估右侧表达式,本例中是个空对象直接量。此OR语句实际上是个会返回评估结果的表达式,然后将结果赋给全局变量 现在,轮到下个文件来使用此模式了,它会获得OR语句,并发现 这导致的结果是,首个包含进来的文件会创建我们的 私有状态(Private State)正如我们刚才所说,由于位于函数内部,在其内部声明的一切内容都是处于该函数的范围内,而不是全局范围。对于隔离我们的代码这真太棒了,此外,它还有个影响是,没有人能调用它。中看不中用。 刚刚我们还谈到,我们创建了 在此函数内声明我们的值的另一结果是,如果某个值不是通过将其附加到我们的全局命名空间或者模块外部的某物的方法来显示公开的,那么外部代码将无法碰到它。事实上,我们刚刚就创建了一些私有值。 CommonJS模块(CommonJS Modules)CommonJS是一个主要由服务端JavaScript运行库(server-side JavaScript runtimes)作者组成的小组,他们一直致力于暴露及访问模块的标准化工作(standardize exposing and accessing modules)。值得注意的是,尽管他们提议的模块系统不是来自于创建JavaScript标准同一小组的一个标准,因此它更多地成为JavaScript运行库作者之间的非正式约定(informal convention)。
该模块规范(Modules specification)的核心可谓开门见山。模块(Modules)在它们自己的上下文中进行评估,并且拥有全局变量 // calculator.js 如果你曾经玩过Node.js,那么你会发现上面的代码很熟悉。这种用Node来实现CommonJS模块的方式是出奇地简单,在node-inspector(一款Node调试器)中查看某个模块时将显示其包装在某个函数内部的内容,此函数正是传递给 有几个node项目(Stitch和Browserify),它们将CommonJS模块带进了浏览器。服务器端组件将这些彼此独立的模块js文件塞进一个单独的js文件中,并在那些代码外面包上生成的模块包装器(generated module wrapper)。 CommonJS主要设计用于服务端JavaScript运行库,而且由于有几个属性使得它们很难在浏览器中进行客户端代码的组织。
异步模块定义(Asynchronous Module Definition)异步模块定义(Asynchronous Module Definition,通常称为AMD)已设计为适合于浏览器的模块格式。它最初只是一个来自CommonJS小组的提议,但此后移到了GitHub上,而且现在伴有一个适用于模块系统作者的测试套件,以便验证对于AMD API的遵从性(compliance)。 AMD的核心是 define('calculator', ['adder'], function(adder) { 由于此模块的定义包在 为了与原本的CommonJS模块提议保持兼容已作出重大努力。当在模块工厂函数中使用 看起来AMD正在成为颇受欢迎的组织客户端JavaScript应用程序的方式。无论是否通过如RequireJS或curl.js、或是像Dojo等最近已采用AMD的JavaScript应用程序等模块资源加载器来组织代码。 这是否意味着JavaScript很烂?(Does this mean JavaScript sucks?)缺乏将代码组织到模块中的语言级别的结构(language level constructs),这可能会让来自于其他语言的开发者感觉很不爽。然而,正由于此缺陷才迫使JavaScript开发者想出他们自己的模块构造模式,我们已经能够随着JavaScript应用程序的发展进行迭代和改进。欲深入了解此主题请访问Tagneto的博客。 想象一下,即使这种功能类型(即Module)在10年前就已包括在语言中。那么他们也不可能想到在服务器上运行大型JavaScript应用程序、在浏览器中异步加载资源、或者像文本模板(text templates)(那些载入器就像RequireJS所做的一样)那样包含资源等诸如此类的需求。 正在考虑将模块(Modules)作为Harmony/ECMAScript 6的语言级别功能。这多亏了模块系统作者们的思想和过去几年的辛勤工作,很可能我们最终得到的语言会适用于构建现代JavaScript应用程序。 |