Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES6 模块、Commond、AMD、CMD的区别 #24

Open
TieMuZhen opened this issue Nov 19, 2021 · 0 comments
Open

ES6 模块、Commond、AMD、CMD的区别 #24

TieMuZhen opened this issue Nov 19, 2021 · 0 comments

Comments

@TieMuZhen
Copy link
Owner

TieMuZhen commented Nov 19, 2021

前言

es6: import / export
commonjs: require / module.exports / exports
amd: require / defined

Commond、AMD、CMD的区别

  • Commond是服务器端的,是同步的。
  • AMD和CMD是浏览器端的,是异步的。

CommonJS规范

Node 应用由模块组成,采用 CommonJS 模块规范。

CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。

var x = 5;
var addX = function (value) {
  return value + x;
};
module.exports.x = x;
module.exports.addX = addX;

上面代码通过module.exports输出变量x和函数addX

require方法用于加载模块。

var example = require('./example.js');

console.log(example.x); // 5
console.log(example.addX(1)); // 6

CommonJS模块的特点如下

  • 所有代码都运行在模块作用域,不会污染全局作用域。
  • 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
  • 模块加载的顺序,按照其在代码中出现的顺序。

AMD、CMD规范

CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。AMD规范则是非同步加载模块,允许指定回调函数。由于Node.js主要用于服务器编程,模块文件一般都已经存在于本地硬盘,所以加载起来比较快,不用考虑非同步加载的方式,所以CommonJS规范比较适用。但是,如果是浏览器环境,要从服务器端加载模块,这时就必须采用非同步模式,因此浏览器端一般采用AMD规范

AMD规范使用define方法定义模块,下面就是一个例子:

define(['package/lib'], function(lib){
  function foo(){
    lib.log('hello world!');
  }

  return {
    foo: foo
  };
});

define 函数:

define([module-name?],[array-of-dependencies?],[module-factory-or-object]);   
  • module-name:模块标识,可以省略。define 函数允许省略第一个参数,因此定义一个匿名模块。这时候模块文件的文件名就是模块标识,即如果这个模块文件名为 A.js ,那么 A 就是模块名。这将带来一个好处,就是模块的高度可重用的。你拿来一个匿名模块,随便放在一个位置就可以使用它,模块名就是它的文件路径。这也很好的符合了 DRY(Don’t Repeat Yourself)原则。
  • array-of-dependencies:所依赖的模块数组,可以省略
  • module-factory-or-object:模块的实现或者一个 JavaScript 对象

define 函数具有异步性,其首先会异步加载第二个参数中列出的依赖模块,当所有的模块被加载后,执行第三个参数的回调函数。

AMD 和 CMD 的区别
CMD 推崇依赖就近,AMD 推崇依赖前置

// CMD
define(function(require, exports, module) {   
    var a = require('./a')   
    a.doSomething()   
    var b = require('./b') // 依赖可以就近书写  
    b.doSomething()  
})
// AMD 
define(['./a', './b'], function(a, b) {   // 依赖必须一开始就写好  
    a.doSomething()     
    b.doSomething()  
})

AMD:速度快、预先加载所有的依赖,直到使用的时候才执行,与CMD相比推荐此法。
CMD:只有真正需要才加载依赖、直到使用的时候才定义依赖。

AMD规范允许输出的模块兼容CommonJS规范,这时define方法需要写成下面这样:

define(function (require, exports, module){
  var someModule = require("someModule");
  var anotherModule = require("anotherModule");

  someModule.doTehAwesome();
  anotherModule.doMoarAwesome();

  exports.asplode = function (){
    someModule.doTehAwesome();
    anotherModule.doMoarAwesome();
  };
});

ES6 模块

require/exports规范是 JavaScript 社区中的开发者自己草拟的规则,得到了大家的承认或者广泛的应用。比如CommonJSAMDCMD 等等。import/export 则是名门正派。TC39 制定的新的 ECMAScript 版本,即 ES6(ES2015)中包含进来。

Node.js 无法直接兼容 ES6。所以现阶段 require/exports 任然是必要且实必须的,所以,目前编写的import/export最终都是编译为require/exports来执行的。

ES6模块和CommonJS模块的差异?

  1. ES6模块在编译时,就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 模块,运行时加载。
  2. CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用;
  3. require 可以做动态加载,import 语句做不到,import 语句必须位于顶层作用域中。
  4. ES6 模块中顶层的 this 指向 undefined,commonJS 模块的顶层 this 指向当前模块。
  5. ES6 模块自动采用严格模式,无论模块头部是否写了 "use strict"。

CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。如:

//name.js
var name = 'William';
setTimeout(() => name = 'Yvette', 200);
module.exports = {
    name
};
//index.js
const name = require('./name');
console.log(name); //William
setTimeout(() => console.log(name), 300); //William

对比 ES6 模块看一下:

ES6 模块的运行机制与 CommonJS 不一样。JS 引擎对脚本静态分析的时候,遇到模块加载命令 import ,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。

//name.js
var name = 'William';
setTimeout(() => name = 'Yvette', 200);
export { name };
//index.js
import { name } from './name';
console.log(name); //William
setTimeout(() => console.log(name), 300); //Yvette
@TieMuZhen TieMuZhen changed the title CommonJS规范 Commond、AMD、CMD的区别 Nov 19, 2021
@TieMuZhen TieMuZhen changed the title Commond、AMD、CMD的区别 ES6 模块、Commond、AMD、CMD的区别 Nov 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant