Javascript——ES6 Module 和 Common JS 模块

15 篇文章 0 订阅
7 篇文章 0 订阅

一、ES6 Module的使用

ES6模块(ECMAScript 2015模块)是JavaScript官方的模块系统,旨在标准化JavaScript中如何编写和消费模块。在ES6模块中,可以使用 importexport 语句来导入和导出变量、函数、类或任何其他对象。

以下是一些基本的ES6模块用法:

1.1导出 (Export)

有两种主要的导出方式:

  • 命名导出(Named Exports)
  • 默认导出(Default Exports)
a.命名导出

你可以导出多个值,每个值都有一个名称。在导入时需要使用相同的名称。

  • 多重性:一个模块可以包含多个命名导出。这使得你可以从同一个模块中导出多个值。
  • 导入语法:必须使用花括号 {} 来导入具体的命名导出,并且必须使用导出时指定的名称,除非在导入时通过 as 关键字重命名。
  • 用例:当模块提供多个功能,或者当你想要组织代码并明确各个导出项的名称时,命名导出非常有用。
// file: myModule.js

// 导出单个特性
export const myVariable = 'someValue';

// 导出多个特性
const a = 'a';
function b() {
  return 'b';
}
class c {
  doSomething() {}
}

// 明确地列出所有要导出的内容
export { a, b, c };
b.默认导出

每个模块可以有一个默认导出。默认导出可以是一个函数、类、对象或任何其他值。导入时,你可以为默认导出指定任意名称

  • 唯一性每个模块文件只能有一个默认导出。这意味着当你使用默认导出时,该模块可以输出一个特定的值作为其主要导出。
  • 导入语法:默认导出的值可以在导入时使用任何名称。因为每个模块只有一个默认导出,所以不需要知道原始名称就可以导入。
  • 用例:通常用于导出模块中最主要或最显而易见的值,比如一个模块只输出一个类或函数。
// file: myDefaultModule.js

// 默认导出整个类
export default class {
  doSomething() {}
}

// 或者默认导出一个函数
export default function () {
  return 'something from default export';
}

// 另一个文件
export default 'Some value';

1.2导入 (Import)

导入模块中的特性时,你需要使用与导出时相对应的语法。

a.导入命名导出
// file: main.js

// 导入单个命名导出
import { myVariable } from './myModule.js';

// 导入多个命名导出
import { a, b, c } from './myModule.js';

// 使用别名导入
import { a as aliasA, b as aliasB } from './myModule.js';

// 导入模块中所有的命名导出,并将它们放入一个对象中
import * as MyModule from './myModule.js';

console.log(MyModule.a); // 访问导入的变量'a'
b.导入默认导出
// 导入默认导出的类或函数,你可以给它取任意的名字
import MyDefaultClass from './myDefaultModule.js';
import someFunction from './myDefaultModule.js';

// 你还可以同时导入默认导出和命名导出
import DefaultItem, { myVariable, a, b, c } from './myModule.js';

动态导入 (Dynamic Imports)

如果你需要根据条件或在执行期间动态地加载模块,可以使用 import() 函数来实现。这会返回一个解析为模块导出的Promise对象。

// 动态导入模块
if (condition) {
  import('./myModule.js').then(module => {
    // 使用模块的导出
    console.log(module.myVariable);
  }).catch(error => {
    // 处理错误情况
    console.error('Module failed to load', error);
  });
}

注意事项

  • ES6模块默认开启严格模式 (use strict)。
  • 模块的顶级声明是模块作用域的(不是全局作用域的)。
  • 模块代码只会执行一次,无论被导入多少次。
  • importexport 语句不能被用在表达式或函数内部,必须位于模块顶层。
  • ES6模块文件的后缀通常是 .js,Node.js 环境也支持 .mjs 后缀。
  • 在HTML中使用模块时,需要在 <script> 标签上设置 type="module" 属性。
  • 路径可以是绝对路径、相对路径或URL,并且可以省略文件扩展名,具体行为取决于运行环境。

二、Common JS模块

CommonJS 是在 Node.js 中使用的模块系统。CommonJS 模块通过 require 函数来加载和 module.exportsexports 对象来导出功能。以下是 CommonJS 模块用法的一些基本概念:

2.1导入模块 (Require)

在 CommonJS 中,你可以使用 require 函数来导入其他模块。该函数接受一个模块标识符(通常是文件的路径)作为参数,并返回该模块导出的内容。

// 导入内置的 fs(文件系统)模块
const fs = require('fs');

// 导入同一目录下的自定义模块
const myModule = require('./myModule');

2.2导出模块 (Exports)

有两种方式可以导出模块中的内容:使用 module.exportsexports

module.exports

你可以将 module.exports 设置为任何类型的值。设置了 module.exports 后,它将成为模块的公开接口。

// file: myModule.js

// 导出一个函数
module.exports = function() {
  console.log('Hello from myModule!');
};

// 或者导出一个对象
module.exports = {
  someFunction: function() { /* ... */ },
  someValue: 'Some string'
};

exports

exportsmodule.exports 的一个引用,意味着你可以使用 exports 来导出单个属性或方法,而不是整个对象。但是,不能直接将 exports 赋值为一个值,因为这样会断开 exportsmodule.exports 之间的连接。

// file: myModule.js

// 导出多个特性
exports.myFunction = function() { /* ... */ };
exports.myVariable = 'My Exported Variable';

请注意,如果同时使用了 module.exportsexports,那么 module.exports 的值会被优先使用,并且 exports 上的任何导出都会被忽略。

2.3使用导出的模块

当你导入一个 CommonJS 模块时,你可以使用其暴露的 API 如下:

// file: main.js

const myModule = require('./myModule');

// 当 myModule.js 使用 module.exports = ...
myModule(); // 如果 myModule 导出了一个函数

// 当 myModule.js 使用 exports.myFunction = ...
myModule.myFunction(); // 如果 myModule 导出了名为 myFunction 的函数

注意事项

  • 在 CommonJS 系统中,模块的加载是同步完成的,这在服务端环境(如 Node.js)中是可行的,因为模块文件通常已经位于本地文件系统中。
  • require 命令用于加载文件模块,并执行该模块的代码,然后返回该模块的 exports 对象。
  • 加载模块的路径可以是绝对的或相对的。若为相对路径,它必须以 ./../ 开始。
  • Node.js 有一个缓存机制,第一次加载之后会缓存模块。后续再加载同一个模块时,将直接从缓存中获取模块的导出结果,而不会重复执行模块代码。

以上就是 CommonJS 模块的基本用法,它形成了 Node.js 应用程序结构和依赖管理的基础。随着 ES6 模块的推广,Node.js 也开始支持 ES6 模块,但 CommonJS 由于其长期存在和广泛使用,在 Node.js 生态中仍然非常重要。

三、ES6 Module 和 Common JS 模块的区别

ES6 Modules(也称为ECMAScript模块或ESM)和CommonJS (CJS) 模块是JavaScript中两种不同的模块化标准。以下是它们之间的一些主要区别:

3.1语法差异

  • ES6 Modules:

    • 使用 import 语句导入其他模块。
    • 使用 exportexport default 导出模块功能。
    // ESM 导入示例
    import { myFunction, myVariable } from './module.js';
    
    // ESM 导出示例
    export const myVariable = 'value';
    export function myFunction() { /* ... */ }
    export default class MyClass { /* ... */ }
    
  • CommonJS:

    • 使用 require() 函数导入其他模块。
    • 使用 module.exportsexports 导出模块功能。
    // CommonJS 导入示例
    const { myFunction, myVariable } = require('./module');
    
    // CommonJS 导出示例
    exports.myVariable = 'value';
    module.exports.myFunction = function() { /* ... */ };
    module.exports = class MyClass { /* ... */ };
    

3.2加载机制差异

  • ES6 Modules:
    • 静态加载:在编译时就确定模块间的依赖关系,允许静态分析和优化,如树摇(tree shaking)。
    • 支持异步加载:可以与 import() 一起使用来实现动态导入。
  • CommonJS:
    • 动态加载:模块的导入解析发生在代码运行时,因此可以根据条件动态地加载模块。
    • 不支持异步加载:通常都是同步加载,尽管有工具和方法可以使其支持异步加载。

3.3执行时机差异

  • ES6 Modules:
    • ES6模块的导入会被提升到模块的顶部,意味着无论在代码的哪个位置调用 import,它都会被当作在文件顶部声明。
  • CommonJS:
    • require() 可以在代码的任何位置调用,并且在调用的那个位置同步地加载和执行模块。

3.4运行环境支持

  • ES6 Modules:
    • 最初只在浏览器中得到原生支持。Node.js从版本13开始支持ES模块,但需要额外的配置(例如,使用 .mjs 文件扩展名或在 package.json 中声明 "type": "module")。
  • CommonJS:
    • 主要在Node.js环境下使用,虽然也可以通过构建工具转换为浏览器可用代码。

3.5互操作性

  • Node.js 提供了一些机制来在ES6模块和CommonJS模块之间进行交互,但这可能会导致复杂性,特别是涉及到默认导出和命名导出的转换。

上述是两种模块系统的基本区别,但随着JavaScript生态的快速发展,一些限制和功能可能会随时间而改变。开发者应该根据项目需求、团队习惯和环境支持情况选择合适的模块系统。

  • 14
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值