ES6模块化与CommonJS模块化异同

76 阅读2分钟

ES6 Module

  • ES6模块化汲取CommonJS和AMD的优点,语法简洁,支持异步加载,可以成为浏览器和服务器通用的模块化方案
  • ES6中模块的定义:ES6新增了两个关键字:exportimport。export用于把模块里的内容暴露出来,import用于引入模块提供的功能
  • 可以使用export default命令,为模块指定默认输出,一个模块只能有一个默认输出,所以export default只能使用一次
  • ES6模块运行机制:ES6模块是动态引用,如果使用import从一个模块加载变量(即import foo from 'foo'),变量不会被缓存,而是成为一个指向被加载模块的引用。等脚本执行时,根据只读引用,到被加载的那个模块中去取值,即模块是运行时进行加载
  • ES6 Module是对模块的引用,即ES6 Module只存只读,不能改变其值,也就是指针指向不能改变,类似于const
  • 对ES6 Module赋值会引起编译报错
  • Es Module`语句运行在代码编译时,import只能声明在该文件的最顶部,不能动态加载语句
// lib.js
export let obj = {};
// main.js
import { obj } from './lib';
obj.prop = 123; // OK
obj = {}; // TypeError

CommonJS

  • 加载模块是同步的,也就是说,加载完成才执行后面的操作
  • 模块是运行时加载
  • 模块就是文件,文件就是模块
  • 主要用于服务器编程,模块都是存在本地硬盘中,加载比较快,所以Node.js采用CommonJS规范
  • CommonJS规范分为三部分
    • module(模块标识):module变量在每个模块内部,就代表当前模块
    • require(模块引用):是对外的接口,用于导出当前模块的方法或变量
    • exports(模块定义):用来加载外部模块,读取并执行js文件,返回该模块的exports对象
  • 注意事项:不能把exports直接指向一个值,这样就相当于切断了 exports 和module.exports 的关系
  • 一个模块的对外接口,就是一个单一的值,不能使用exports输出,必须使用 module.exports输出。module.exports=function(x){console.log(x);}
  • CommonJS是对模块的浅拷贝,可以对require引入的变量重新赋值(改变指针指向)
  • 一旦输出一个值,模块内部的变化就影响不到这个值
// lib.js
var counter = 3;
function incCounter() {
  counter++;
}
module.exports = {
  counter: counter,
  incCounter: incCounter,
};
 // main.js
var mod = require('./lib');

console.log(mod.counter);  // 3
mod.incCounter();
console.log(mod.counter); // 3
  • mod.counter是一个原始类型的值,会被缓存。除非写成一个函数,才能得到内部变动后的值

ES6 Module和CommonJS的相同点

  • 都可以对引入的对象进行赋值,即对对象内部属性的值进行改变

--------------------------------------------------------------------------------------------2024.5.8每日一题