Skip to content

ES6 中的模块化

CommonJS 规范

什么是 CommonJS

CommonJS JS社区在 2009 年提出的一系列标准的统称,其中包含了模块、文件、IO、控制台等标准。Node.js 的实现中采用了CommonJS标准的一部分,并对它进行了一些调整。我们日常工作中所说的CommonJS实际上是指Node.js中实现的版本,不是它的原始定义。CommonJS 中规定每个文件是一个模块。

CommonJS 导入导出

  • 模块导出 使用module.exportsexports对象将模块中的内容导出,以便其他模块可以使用。

    js
    // math.js
    function add(a, b) {
      return a + b;
    }
    
    module.exports = add;
  • 模块导入 使用require函数导入其他模块。

    js
    // app.js
    const add = require("./math");
    
    const result = add(2, 3);
    console.log(result); // 输出 5

CommonJS 特点

CommonJS规范加载模块是同步的,只有加载完成,才能执行后面的操作。

  • CommonJS规范中,模块化是通过moduleexportsrequire这三个核心概念来实现的:

    • 每个文件就是一个模块,有自己的作用域。每个模块内部,module变量代表当前模块,是一个对象,它的exports属性(即 module.exports)是对外的接口。

    • module.exports 属性表示当前模块对外输出的接口,其他文件加载该模块,实际上就是读取module.exports变量。

    • require函数用于导入其他模块。它接受一个模块的路径或名称,并返回该模块导出的内容。

ES6 module 规范

ES6 模块(也称为ECMAScript模块或ES模块)是JavaScript的一种标准化模块系统,旨在解决CommonJSAMD模块系统的一些问题。ES6模块在浏览器和服务器端环境(如Node.js)中都可以使用。

ES6 module 导入导出

  • 模块导出 使用export关键字将模块中的内容导出

    js
    // math.js
    export function add(a, b) {
      return a + b;
    }
  • 模块导入 使用import关键字导入其他模块

    js
    // app.js
    import { add } from "./math.js";
    
    const result = add(2, 3);
    console.log(result); // 输出 5

ES6 模块的特点

  1. 静态分析:ES6 模块在编译时就能确定模块的依赖关系,有助于进行静态分析和优化。
  2. 异步加载:ES6 模块支持异步加载,适合在浏览器环境中使用。
  3. 标准化:ES6 模块是JavaScript的标准模块系统,得到广泛支持。
  4. 兼容性:旧版浏览器和 Node.js 需要使用工具(如 Babel)进行转译或配置(如使用 --experimental-modules 标志)才能支持 ES6 模块。

ES6 module 和 CommonJS module 的区别

  1. CommonJSrequire语法是同步的,导致CommonJS模块规范只适合用在服务端,而ES6模块无论是在浏览器端还是服务端都是可以使用的,但是在服务端中,还需要遵循一些特殊的规则才能使用(使用.mjs扩展名、设置 "type": "module"等等)

  2. CommonJS模块输出的是一个值的拷贝,而ES6模块输出的是值的引用(意思是,CommonJS一旦输出一个值,模块内部的变化不会影响到这个值;ES6原始值变了 import加载的值也会跟着变化)

  3. CommonJS模块是运行时加载,而ES6模块是编译时输出接口,使得对JS的模块进行静态分析成为了可能

  4. 模块顶层的this指向,在CommonJS顶层,this指向当前模块;而在ES6模块中,this 指向 undefined

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

ES6 module、CommonJS module 循环引用的问题

循环加载指的是 a 脚本的执行依赖 b 脚本,b 脚本的执行依赖 a 脚本

  1. CommonJS模块是加载时执行。一旦出现某个模块被“循环加载”,就只输出已经执行的部分,没有执行的部分不会输出。
  2. ES6模块对导出模块,变量,对象是动态引用,遇到模块加载命令import时不会去执行模块,只是生成一个指向被加载模块的引用,保证真正取值时能够取到值,只要引用是存在的,代码就能执行。

如有转载或 CV 的请标注本站原文地址