Javascript 为什么CommonJS只适用于非浏览器应用程序?

Javascript 为什么CommonJS只适用于非浏览器应用程序?,javascript,architecture,components,design-patterns,commonjs,Javascript,Architecture,Components,Design Patterns,Commonjs,为什么不将它用作Javascript的通用组件模式,包括浏览器执行的Javascript 乍一看,这似乎是一个很好的模块化我目前正在进行的项目的方法,该项目由一个大型Javascript代码库组成,有很多组件,其中一些组件相互作用。CommonJS确实适合浏览器,但有一些警告。CommonJS模块模式非常好(我有偏见地认为),也是ECMAScript Harmony(计划中的JavaScript语言的下一个版本)模块系统的良好垫脚石。具体来说,Harmony模块将无法访问全局(“窗口”)对象 有

为什么不将它用作Javascript的通用组件模式,包括浏览器执行的Javascript


乍一看,这似乎是一个很好的模块化我目前正在进行的项目的方法,该项目由一个大型Javascript代码库组成,有很多组件,其中一些组件相互作用。

CommonJS确实适合浏览器,但有一些警告。CommonJS模块模式非常好(我有偏见地认为),也是ECMAScript Harmony(计划中的JavaScript语言的下一个版本)模块系统的良好垫脚石。具体来说,Harmony模块将无法访问全局(“窗口”)对象

有些人声称CommonJS模块不适合浏览器的原因是,如果没有服务器端的帮助,它们无法通过标签加载。例如,假设您有一个markdown库,它导出一个“convertToHTML”函数。然后,您可以制作一个如下所示的模块:

var convertToHTML = require("markdown").convertToHTML;
exports.mangleSomeText = function() {
    // do something then call convertToHTML
}
define(function(require, exports, module) {

var convertToHTML = require("markdown").convertToHTML;
exports.mangleSomeText = function() {
    // do something then call convertToHTML
}

});
由于一些原因,这无法通过脚本标记工作(范围未包装,因此convertToHTML将附加到窗口,通常不会定义require,并且需要为每个模块分别创建导出)

带有少量服务器端帮助的客户端库可以轻松地通过脚本标记加载。或者,通过XMLHttpRequest加载脚本并执行eval()的客户端库也可以工作,尽管调试体验通常没有那么好

目前一个相当合理的解决方案是,尽管它也是CommonJS成员之间有争议的话题。使用RequireJS,您可以编写如下模块:

var convertToHTML = require("markdown").convertToHTML;
exports.mangleSomeText = function() {
    // do something then call convertToHTML
}
define(function(require, exports, module) {

var convertToHTML = require("markdown").convertToHTML;
exports.mangleSomeText = function() {
    // do something then call convertToHTML
}

});
我们所做的只是在模块周围添加define()位。(您也可以让服务器很容易地完成这项工作,这样您甚至不需要手动键入define部分)

我个人已经在几个项目上使用了RequireJS,并且发现它是一种不用服务器端代码就可以使用CommonJS模块的简单方法。还有许多其他解决方案,如果您不依赖于运行静态JS文件,那么标准CommonJS模块是一个不错的选择


(免责声明:我启动了CommonJS项目,所以我显然有偏见。)

CommonJS就像AdobeAIR一样,我认为它是一种不会在经典浏览器中运行的api。但它仍然是javascript,使用不同的api。例如,在浏览器中,您有dhtml或dom,在公共js中,您有另一个与浏览器无关的api。为了学究,ECMAScript Harmony模块确实可以访问全局对象,只是不是共享的顶级词法作用域。是否可以编写一个既兼容requirejs又兼容commonjs的模块?@AndersonGreen是的,只需检测底部的
define
exports
变量,并有条件地同时检测这两组代码。@seanClarkhes我认为这里有输入错误。你能解释一下“有条件地和两套代码”是什么意思吗?@AndersonGreen我写了一篇博客文章,举了一个例子: