es6模块(amd标准)和node使用的标准(commonjs)模块的区别

  1. CommonJs模块是在运行加载,ES6是在编译时输出接口(使得静态分析成为可能,才可以对代码执行treesharking)
  2. CommonJs模块输出的是一个值的复制(不变),ES6模块输出的是值的引用(可变)。

注:es6的export语句输出的接口与其对应的值是动态绑定关系,通过该接口可以取到模块内部的实时值。CommonJs的规范完全不同,CommonJs模块输出的是值得缓存,不能动态更新。

CommonJs模块的导出示例

  1. //lib.js
  2. var counter = 1;
  3. function incCounter(){
  4. counter ++;
  5. }
  6. module.exports = {
  7. counter:counter,
  8. incCounter: incCounter
  9. }
  10. // main.js
  11. var mod = require("./lib.js")
  12. console.log(mod.counter) // 1
  13. mod.incCounter();
  14. console.log(mod.counter) // 1

说明lib.js模块加载以后内部变化就不会影响到输出的值。因为mod.counter是一个原始类型的值,会被缓存。如果写成函数,就可以得到内部变动的值。

  1. //lib.js
  2. var counter = 1;
  3. function incCounter(){
  4. counter ++;
  5. }
  6. module.exports = {
  7. get counter(){
  8. return counter
  9. },
  10. incCounter: incCounter
  11. }
  12. // main.js
  13. var mod = require("./lib.js")
  14. console.log(mod.counter) // 1
  15. mod.incCounter();
  16. console.log(mod.counter) // 2

ES6模块的导出示例

  1. // lib.js
  2. export let counter = 1;
  3. export function incCounter(){
  4. counter ++;
  5. }
  6. // main.js
  7. import {counter, incCounter} from './lib.js'
  8. console.log(counter) //1
  9. incCounter()
  10. console.log(counter) //2

ES6模块是动态引用,JS引擎对脚本做静态分析时,遇到模块加载命令import会生成一个只读对象的引用,不会缓存值,等待脚本执行期间,再根据这个只读引用到被加载的模块中取值。
Es6在编译时做静态分析,可以使用tree-shaking功能。
注意,ES6模块整体加载所在的那个对象是只读的,应该是静态的,所以不允许运行时改变。

  1. // lib.js
  2. export let obj = {}
  3. // main.js
  4. import {obj} from './lib.js'
  5. obj.prop = 12 //可以执行
  6. obj = {name:"oob"} // TypeError

不允许给引入的对象赋值

ES6中,export命令只能出现在模块顶层,即不能放在函数或条件语句块中(否则没法做静态优化),在模块的任何位置都可以。

import()类似于Node的require方法,主要区别是,import()是异步加载,require是同步加载。commonjs是同步加载的,没法直接使用tree-shaking功能。