我仍然对CommonJS,AMD和RequireJS感到困惑。即使阅读了很多。
我知道CommonJS(以前称为ServerJS)是一个用于在浏览器外部使用该语言时定义一些JavaScript规范(即模块)的组。 CommonJS模块规范有一些实现,比如Node.js或RingoJS,对吗?
CommonJS,异步模块定义(AMD)和RequireJS之间有什么关系? RequireJS是CommonJS模块定义的实现吗?如果是的话,那么什么是AMD呢?
答案 0 :(得分:735)
RequireJS 实施 AMD API (source)。
CommonJS 是一种在exports
对象的帮助下定义模块的方法,它定义了模块内容。简而言之,CommonJS实现可能会这样工作:
// someModule.js
exports.doSomething = function() { return "foo"; };
//otherModule.js
var someModule = require('someModule'); // in the vein of node
exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };
基本上,CommonJS指定您需要一个require()
函数来获取依赖项,一个exports
变量来导出模块内容和一个模块标识符(它描述了相关模块的位置)到此模块)用于要求依赖项(source)。 CommonJS有各种实现,包括你提到的 Node.js 。
CommonJS并没有特别考虑到浏览器的设计,因此它不能很好地适应浏览器环境(我真的没有这方面的资源 - 它只是在任何地方都这样说,包括the RequireJS site. )显然,这与异步加载等有关。
另一方面,RequireJS实现了AMD,其设计适合浏览器环境(source)。显然,AMD最初是作为CommonJS Transport格式的衍生产品,并发展成为自己的模块定义API。因此两者之间的相似之处。 AMD中的新功能是define()
函数,它允许模块在加载之前声明其依赖项。例如,定义可以是:
define('module/id/string', ['module', 'dependency', 'array'],
function(module, factory function) {
return ModuleContents;
});
因此,CommonJS和AMD是 JavaScript 模块定义API,它们具有不同的实现,但都来自相同的起源。
为了让您更加困惑,RequireJS作为AMD实现,提供了一个CommonJS包装器,因此几乎可以直接导入CommonJS模块以与RequireJS一起使用。
define(function(require, exports, module) {
var someModule = require('someModule'); // in the vein of node
exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };
});
我希望这有助于澄清事情!
答案 1 :(得分:194)
CommonJS不止于此 - 它是一个为JavaScript定义通用API和生态系统的项目。 CommonJS的一部分是Module规范。 Node.js和RingoJS是服务器端JavaScript运行时,是的,它们都基于CommonJS模块规范实现模块。
AMD(异步模块定义)是模块的另一个规范。 RequireJS可能是AMD最受欢迎的实现。与CommonJS的一个主要区别是AMD指定模块是异步加载 - 这意味着模块是并行加载的,而不是通过等待加载完成来阻止执行。
由于这一点,AMD通常更多地用于客户端(浏览器内)JavaScript开发,而CommonJS模块通常用于服务器端。但是,您可以在任一环境中使用任一模块规范 - 例如,RequireJS提供directions for running in Node.js,browserify是可以在浏览器中运行的CommonJS模块实现。答案 2 :(得分:183)
CommonJS 和 AMD 是关于如何在javascript应用程序中声明模块及其依赖项的规范(或格式)。
RequireJS 是符合AMD标准的脚本加载程序库,curljs是另一个示例。
// package/lib is a dependency we require
var lib = require( "package/lib" );
// behavior for our module
function foo(){
lib.log( "hello world!" );
}
// export (expose) foo to other modules as foobar
exports.foobar = foo;
// package/lib is a dependency we require
define(["package/lib"], function (lib) {
// behavior for our module
function foo() {
lib.log( "hello world!" );
}
// export (expose) foo to other modules as foobar
return {
foobar: foo
}
});
该模块的其他地方可以用于:
require(["package/myModule"], function(myModule) {
myModule.foobar();
});
实际上,CommonJS不仅仅是一个API声明,只有一部分涉及到它。 AMD最初是作为CommonJS列表中模块格式的规范草案,但未达成完全共识,格式的进一步发展转移到amdjs group。关于哪种格式更好的说法CommonJS试图涵盖更广泛的关注点,并且鉴于其同步特性,它更适合服务器端开发,并且AMD更适合客户端(浏览器)开发,因为它具有异步性和事实上,它的根源在于Dojo的模块声明实现。
答案 3 :(得分:24)
<强> AMD 强>:
<强> CommonJS的强>:
<?php
class New_menu_model extends CI_Model {
function get_domains() {
$result = $this->db->get ( 'domenii' );
$menu = array(
'menus' => array(),
'parent_menus' => array()
);
foreach($result->result_array() as $row)
{
//creates entry into menus array with current menu id ie. $menus['menus'][1]
$menu['menus'][$row['id_domeniu']] = $row;
//creates entry into parent_menus array. parent_menus array contains a list of all menus with children
$menu['parent_menus'][$row['parent']][] = $row['id_domeniu'];
}
return $menu;
}
function buildMenu($parent, $menu) {
$html = "";
if (isset($menu['parent_menus'][$parent])) {
$html .= "<ul>";
foreach ($menu['parent_menus'][$parent] as $menu_id) {
if (!isset($menu['parent_menus'][$menu_id])) {
$html .= "<li><a href='#'>" . $menu['menus'][$menu_id]['nume_domeniu'] . "</a></li>";
}
if (isset($menu['parent_menus'][$menu_id])) {
$html .= "<li><a href='#'>" . $menu['menus'][$menu_id]['nume_domeniu'] . "</a>";
$html .= $this->buildMenu($menu_id, $menu);
$html .= "</li>";
}
}
$html .= "</ul>";
}
return $html;
}
}
?>
强制执行的define()包装器。 答案 4 :(得分:12)
将JavaScript程序模块化为几个文件并从child-modules
调用main js module
是很正常的。
事情是JavaScript没有提供这个。即使在今天的Chrome和FF的最新浏览器版本中也是如此。
但是,JavaScript中是否有任何关键字可以调用另一个JavaScript模块?
对于许多人来说,这个问题可能是世界彻底崩溃的原因,因为答案是否。
在ES5(2009年发布)中,JavaScript没有导入,包含或需要等关键字。
ES6保存了当天(2015年发布)提议导入关键字(https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/import),但没有浏览器实现此功能。
如果您使用Babel 6.18.0并仅使用ES2015选项进行转换
import myDefault from "my-module";
您将再次获得require
。
"use strict";
var _myModule = require("my-module");
var _myModule2 = _interopRequireDefault(_myModule);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
这是因为require
表示将从Node.js加载模块。 Node.js将处理从系统级文件读取到包装函数到模块的所有内容。
因为JavaScript函数是表示模块的唯一包装器。
我对CommonJS和AMD感到很困惑?
CommonJS和AMD只是两种不同的技术,如何克服JavaScript“缺陷”来加载智能模块。
答案 5 :(得分:2)
AMD
CommonJS :
示例
upper.js文件
exports.uppercase = str => str.toUpperCase()
main.js文件
const uppercaseModule = require('uppercase.js')
uppercaseModule.uppercase('test')
摘要
资源: