js模块化的进程里,出现了很多模块化的方案,commonjs,requirejs(AMD),CMD。随着ES6标准的发布,import/export的规范也被广泛使用了。只是浏览器的支持程度不高,需要配合转码工具使用。ES6的模块化和之前社区的commonjs模块化到底有什么区别呢?

Commonjs的require和module.exports

  • require是个函数,动态加载,也因此
1.require导入是在运行时,理论上可以在任意地方调用require导入模块;
2.require()的路径可以是表达式:require('/app' + '/index');
  • require返回对应module.exports对象的浅拷贝
1.如果是module.exports里的基本类型的值,会得到该值的副本
2.如果是module.exports里的对象类型的值,会得到该值的引用

ES6的import和export

  • import在编译时确定导入
1.路径只能是字符串常量
2.import会被提升到文件最顶部
3.导入的变量是只读的
  • import导入的是值引用,而不是值拷贝
1.模块内部值发生变化,会对应影响到引用的地方
2.import导入与导出需要有一一映射关系,类似解构赋值。

代码说明一下两者的区别

Commonjs

// a.jslet a = 0;const count = () => {    a++;}setTimeout(function(){    a++;    console.log('in module the a is ' + a);}, 500);module.exports = {    a,    count,};// b.jslet foo = require('a.js');foo.count();setTimeout(function(){    console.log('in require the a is ' + foo.a);}, 1000);// 输出// in the module the a is 2// in the require the a is 0

因为foo是一份浅拷贝,所以a是require导入时export里a的值;而count是一个函数,foo.count是这个函数的一个引用,所以调用时作用域是它声明处一样,也就是它修改的a是exports里的,而不是foo.a。

Es6 module

// a.jslet a = 0;const count = () => {    a++;}setTimeout(function(){    a++;    console.log('in module the a is ' + a);}, 500);export {    a,    count,};// b.jsimport { a, count } from 'a.js';count();setTimeout(function(){    console.log('in require the a is ' + a);}, 1000);// 输出// in the module the a is 2// in the require the a is 2

可以看出,很重要的一个区别就是一个基本值是否会同步变化,