前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CommonJS,AMD,CMD和ES6的对比

CommonJS,AMD,CMD和ES6的对比

作者头像
码客说
发布2019-10-22 17:00:23
1.2K0
发布2019-10-22 17:00:23
举报
文章被收录于专栏:码客码客

四种常见的规范

CommonJS

前端浏览器不支持,用于服务器,Nodejs中使用的是这个规范

代码语言:javascript
复制
exports.area = function(r) {
   return Math.PI * r * r;
}
exports.circleCumference= function(r) {
   return Math.PI * r * r;
}

CommonJS的核心思想就是通过 require 方法来同步加载所要依赖的其他模块,然后通过 exports 或者 module.exports 来导出需要暴露的接口。

AMD

浏览器端的模块,不能采用后端使用的CommonJS的”同步加载”(synchronous),只能采用”异步加载”(asynchronous),这就是AMD规范诞生的背景。

AMD是RequireJS在推广过程中对模块定义的规范化产出。

AMD规范则是非同步加载模块,允许指定回调函数。

AMD标准中,定义了下面两个API:

  • require([module], callback)
  • define(id, [depends], callback) 即通过define来定义一个模块,然后使用require来加载一个模块。 并且,require还支持CommonJS的模块导出方式。

test.js

代码语言:javascript
复制
define(['package/lib',...], function(lib) {
    function foo () {
        lib.log('hello world');
    }

    return {
      foo: foo
    }
});

require(['test'], function(test) {
  test.foo()
})

CMD

CMD是SeaJS在推广过程中对模块定义的规范化产出。

CMD是同步模块定义。

代码语言:javascript
复制
//所有模块都通过define来定义
define(function(require, exports, module) {  
  // 通过require引入依赖
  var $ = require('jquery');
  var Spinning = require('./spinning');
  exports.doSomething = ...
  module.exports = ...
})

二者的区别是前者是对于依赖的模块提前执行,而后者是延迟执行。 前者推崇依赖前置,而后者推崇依赖就近,即只在需要用到某个模块的时候再require。

ES6—export/import

在ES6中,我们可以使用 import 关键字引入模块,通过 exprot 关键字导出模块,功能较之于前几个方案更为强大,也是我们所推崇的,但是由于ES6目前无法在浏览器中执行,所以,我们只能通过babel将不被支持的import编译为当前受到广泛支持的 require

代码语言:javascript
复制
import App from './App.vue'
export default {
   props: ['num']
}

使用注意点

AMD和CMD区别

规范

AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。 CMD 是 SeaJS 在推广过程中对模块定义的规范化产s出。 类似的还有 CommonJS Modules/2.0 规范,是 BravoJS 在推广过程中对模块定义的规范化产出。

这些规范的目的都是为了 JavaScript 的模块化开发,特别是在浏览器端的。 目前这些规范的实现都能达成浏览器端模块化开发的目的

区别:

  1. 定位有差异。 RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。 Sea.js 则专注于 Web 浏览器端,同时通过 Node 扩展的方式可以很方便跑在 Node 环境中。
  2. 遵循的规范不同。 RequireJS 遵循 AMD(异步模块定义)规范,Sea.js 遵循 CMD (通用模块定义)规范。规范的不同,导致了两者 API 不同。 Sea.js 更贴近 CommonJS Modules/1.1 和 Node Modules 规范。 CMD 推崇依赖就近,AMD 推崇依赖前置。看代码: // CMD define(function(require, exports, module) { var a = require('./a') a.doSomething() // 此处略去 100 行 var b = require('./b') // 依赖可以就近书写 b.doSomething() // ... }) // AMD 默认推荐的是 define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好 a.doSomething() // 此处略去 100 行 b.doSomething() //... }) 虽然 AMD 也支持 CMD 的写法,同时还支持将 require 作为依赖项传递,但 RequireJS 的作者默认是最喜欢上面的写法,也是官方文档里默认的模块定义写法。
  3. 推广理念有差异。 RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。 Sea.js 不强推,采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。
  4. 对开发调试的支持有差异。 Sea.js 非常关注代码的开发调试,有 nocache、debug 等用于调试的插件。 RequireJS 无这方面的明显支持。
  5. 插件机制不同。 RequireJS 采取的是在源码中预留接口的形式,插件类型比较单一。 Sea.js 采取的是通用事件机制,插件类型更丰富。
  6. 执行机制不同。 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。 不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。 CMD 推崇 as lazy as possible.
  7. API差异。 AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。 比如 AMD 里,require 分全局 require 和局部 require,都叫 require。 CMD 里,没有全局 require,而是根据模块系统的完备性,提供 seajs.use 来实现模块系统的加载启动。 CMD 里,每个 API 都简单纯粹

ES6 import时如何正确使用{ }

导出变量/方法

代码语言:javascript
复制
export const A = 42;
export const api = {
  
};
export function myfunc() {
  
};

var myapi = {};
export {myapi};

导出默认

代码语言:javascript
复制
// 导出默认
export default 42;
export default {

};
export default function() {
  
};
var myapi = {};
export { myapi as default };

导入变量/方法

导入变量/方法的时候变量和方法名必须和导出时一致

代码语言:javascript
复制
import { A,api,myfunc,myapi } from './A'
// 导入设置别名
import { A as AA, myfunc as afunc } from './A'

导入默认

导入默认时变量和方法名可自定义

代码语言:javascript
复制
import A from './A'
// 导入设置别名
import { default as myApi } from './A';

详解

而我们这里要说的是在使用import语法引用模块时,如何正确使用{}

假如有一个B.js,想要通过import语法引用模块A.js,那么可以这么写:

代码语言:javascript
复制
// B.js
import A from './A'

而上面的代码生效的前提是,只有在如下A.js中有默认导出export default语法时才会生效。

也就是:

代码语言:javascript
复制
// A.js
export default 42

在这种不使用{}来引用模块的情况下,import模块时的命名是随意的

即如下引用命名都是正确的:

代码语言:javascript
复制
// B.js
import A from './A'
import MyA from './A'

因为它总是会解析到A.js中默认的export default


而下面是使用了花括号命名的方式{A}来导入A.js

代码语言:javascript
复制
import { A } from './A'

上面代码生效的前提是,只有在模块A.js中有如下命名导出Aexport name的代码,也就是:

代码语言:javascript
复制
export const A = 42

而且,在明确声明了命名导出后,那么在另一个js中使用{}引用模块时,import时的模块命名是有意义的,如下:

代码语言:javascript
复制
// B.js
import { A } from './A'                 // 正确,因为A.js中有命名为A的export
import { myA } from './A'               // 错误!因为A.js中没有命名为myA的export

要想上述代码正确执行,你需要明确声明每一个命名导出:

代码语言:javascript
复制
// A.js
export const myA = 42
export const myB = 43
export default 42

一个模块中只能有一个默认导出export default,但是却可以有任意命名导出(0个、1个、多个)

你也可以如下,一次性将他们导入

代码语言:javascript
复制
// B.js
import A, { myA, myB } from './A'

这里我们使用导入默认导出A,以及命名导出myAmyB

我们甚至可以在导入的时候重命名导入:

代码语言:javascript
复制
import A, { myA as AA, myB as BB } from './A'

也可以这样导出

代码语言:javascript
复制
var api = {

}

export function myfunc() {};  
export default function() {};  

export { api }
export { api as default };

分别对应的导入

代码语言:javascript
复制
import myApi, { api,myfunc } from './A'
// 上面的导入的myApi和下面的一样
import { default as myApi } from './A';  

myfunc();

总结:模块的默认导出通常是用在你期望该从模块中获取到任何想要的内容;而命名导出则是用于一些有用的公共方法,但是这些方法并不总是必要的。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-07-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 四种常见的规范
    • CommonJS
      • AMD
        • CMD
          • ES6—export/import
          • 使用注意点
            • AMD和CMD区别
              • ES6 import时如何正确使用{ }
                • 导出变量/方法
                • 导出默认
                • 导入变量/方法
                • 导入默认
                • 详解
            相关产品与服务
            命令行工具
            腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档