JS模块的导出和引入

模块规范

在 JavaScript 中,有两种常见的模块化规范:CommonJS 和 ES6。

  • CommonJS 是 Node.js 的默认规范,它使用 require 和 module.exports 来导入和导出模块。
  • ES6 是 ECMAScript 2015 的标准,它使用 import 和 export 来导入和导出模块。这两种规范有什么概念和区别呢?我们来看看。

概念和区别

  1. 首先,概念上,CommonJS 是基于值的导出和导入,也就是说,当我们导出一个模块时,我们实际上是导出了一个对象的拷贝。当我们导入一个模块时,我们实际上是获取了一个对象的引用。这意味着,如果我们在导出后修改了模块内部的值,那么导入的模块也会受到影响。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // a.js
    let a = 1;
    module.exports = a;

    // b.js
    let a = require("./a");
    console.log(a); // 1
    a = 2;
    console.log(a); // 2

    // c.js
    let a = require("./a");
    console.log(a); // 1

    可以看到,当我们在 b.js 中修改了 a 的值后,c.js 中导入的 a 并没有改变,因为它们是不同的对象引用。

    而 ES6 是基于名称的导出和导入,也就是说,当我们导出一个模块时,我们实际上是导出了一个变量的声明。当我们导入一个模块时,我们实际上是创建了一个变量的绑定。这意味着,如果我们在导出后修改了模块内部的值,那么导入的模块也会同步更新。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // a.js
    export let a = 1;

    // b.js
    import { a } from "./a";
    console.log(a); // 1
    a = 2;
    console.log(a); // 2

    // c.js
    import { a } from "./a";
    console.log(a); // 2

    可以看到,当我们在 b.js 中修改了 a 的值后,c.js 中导入的 a 也跟着改变了,因为它们是同一个变量绑定。

  2. 其次,区别上,CommonJS 是同步的加载方式,也就是说,当我们使用 require 时,它会立即执行模块代码,并返回结果。这适合于服务器端的环境,因为服务器端的模块通常都已经安装好了,不需要等待网络请求。但是,在浏览器端的环境中,这种方式就不太合适了,因为浏览器端的模块通常需要从远程服务器获取,如果使用同步的方式加载,就会造成页面阻塞和性能下降。

    而 ES6 是异步的加载方式,也就是说,当我们使用 import 时,它会返回一个 promise 对象,并且不会阻塞后面的代码执行。这适合于浏览器端的环境,因为浏览器端的模块可以利用网络请求来并行加载,并且不会影响页面渲染和交互。但是,在服务器端的环境中,这种方式就需要额外的配置和工具来支持。

    总之,CommonJS 和 ES6 都是 JavaScript 的模块化规范,它们有不同的概念和区别。在实际开发中,我们需要根据不同的场景和需求来选择合适的规范,并且可以使用一些工具和转换器来兼容不同的规范。