为什么不将其作为Javascript的通用组件模式,包括在浏览器执行的Javascript中使用?
乍一看,这似乎是一种很好的方式来对我目前正在处理的项目进行模块化,该项目由大量的Javascript代码库组成,其中有许多组件,其中一些组件相互交互。
为什么不将其作为Javascript的通用组件模式,包括在浏览器执行的Javascript中使用?
乍一看,这似乎是一种很好的方式来对我目前正在处理的项目进行模块化,该项目由大量的Javascript代码库组成,其中有许多组件,其中一些组件相互交互。
对于浏览器而言,CommonJS确实是适合的,但需要注意一些细节。CommonJS模块模式非常好用(在我个人看来),并且也是 ECMAScript Harmony(JavaScript语言的下一个版本)提出的模块系统的一个好的过渡方案。具体来说,Harmony模块将无法访问全局对象(“window”对象)。
有些人认为CommonJS模块不适合于浏览器,原因在于它们不能通过<script>标签直接加载,需要一些服务器端的帮助。例如,假设你有一个能够输出“convertToHTML”函数的markdown库,你可以创建以下这样一个模块:
var convertToHTML = require("markdown").convertToHTML;
exports.mangleSomeText = function() {
// do something then call convertToHTML
}
这种方法不能通过脚本标签工作的原因有几个(作用域没有包装,所以 convertToHTML 会被附加到 window 上,require 通常不会被定义,exports 需要为每个模块单独创建)。
一个带有一点服务器端帮助的客户端库可以轻松地通过脚本标签加载。或者,客户端库可以通过 XMLHttpRequest 加载脚本并执行 eval(),虽然调试体验通常不太好。
目前一个相当合理的解决方案,但也是 CommonJS 成员之间争议的焦点,是RequireJS。使用 RequireJS,您可以像这样编写您的模块:
define(function(require, exports, module) {
var convertToHTML = require("markdown").convertToHTML;
exports.mangleSomeText = function() {
// do something then call convertToHTML
}
});
我们所做的就是在模块周围添加了define()部分。(你很容易也可以让服务器这样做,这样你甚至不需要手动编写定义部分)。
我个人已经在几个项目中使用了RequireJS,并发现它是一种简单的方法,可以在没有服务器端的情况下使用CommonJS模块。还有许多其他解决方案,如果您不依赖于运行静态JS文件,则标准的CommonJS模块是一个很好的选择。
(ObDisclaimer:我开始了CommonJS项目,所以我显然是有偏见的。)
define
和 exports
变量,并有条件地同时处理两组代码。 - Sean Clark Hess