CommonJS和ES6 Module的区别

71 阅读2分钟
  • 模块化进程:

    最开始0=>IIFE(立即调用函数)= >AMD/CMD/CommonJS=>UMD=>ES Module

  • CommonJS

    CommonJS是服务端模块规范,Node.js采用了这种规范。

    CommonJS的 require 语法是同步的,当使用require 加载一个模块的时候,必须要等这个模块加载完后,才会执行后面的代码。NodeJS 是服务端,使用 require 语法加载模块,一般是一个文件,只需要从本地硬盘中读取文件,它的速度是比较快的。但是在浏览器端文件一般存放在服务器或者CDN上,如果使用同步的方式加载一个模块还需要由网络来决定快慢,可能时间会很长,这样浏览器很容易进入“假死状态”。所以异步加载的,比较适合在浏览器端使用。

    用法:require() module.exports

  //a.js
  var count = 11;
  function counter() {
      count++;
  }
  module.exports = {
      count: count,
      counter: counter
  }
  //main.js
  var mod = require('./a.js');
  mod.count;  //1
  mod.counter();
  mod.count;  //1
//a.js
   export let count = 11;
   export function counter() {
       count++;
   }
   //main.js
   import {count,counter} from './a.js';
   mod.count;  //1
   mod.counter();
   mod.count;  //2

特点:1.require()是同步加载模块 2.运行时加载 3.输出值的拷贝;即一旦输出某个值,模块内部的变化影响不到这个值,外部引用这个值不会变

  • E6S Module

    用法:import export

    特点:1.import是异步加载模块 2.编译时加载 输出接口 3.输出值的引用,import的时候是个只读引用,等到真正执行时再去模块取值;动态引用

    import命令输入的变量都是只读的,不能在加载模块的脚本里更改接口

 import {a} from './xxx.js'
 a = {}; // Syntax Error : 'a' is read-only;

如果a是一个对象,改写a的属性是被允许的

import {a} from './xxx.js'
a.foo = 'hello'; // 合法操作
  • 因为两个模块加载机制的不同,所以在对待循环加载的时候,它们会有不同的表现。CommonJS遇到循环依赖的时候,只会输出已经执行的部分,后续的输出或者变化,是不会影响已经输出的变量。而ES6模块相反,使用import加载一个变量,变量不会被缓存,真正取值的时候就能取到最终的值;

  • 关于模块顶层的this指向问题,在CommonJS顶层,this指向当前模块;而在ES6模块中,this指向undefined

  • 关于两个模块互相引用的问题,在ES6模块当中,是支持加载CommonJS模块的。但是反过来,CommonJS并不能requireES6模块,在NodeJS中,两种模块方案是分开处理的。