CommonJS和ESM:JavaScript模块化规范对比

41 篇文章 2 订阅
10 篇文章 0 订阅

在现代的JavaScript开发中,模块化是一个至关重要的概念,它有助于将代码拆分为独立的、可维护的部分,使开发过程更加高效和可靠。在JavaScript社区中,有两种主要的模块化规范:CommonJS(通用模块化规范)和ESMECMAScript模块)规范。本文将深入探讨这两种规范的异同点、应用场景以及注意事项。

公众号:Code程序人生,个人网站:https://creatorblog.cn

CommonJS规范

CommonJS是一种早期引入的模块化规范,最初用于服务器端JavaScript(如Nodejs)。它的主要特点包括:

  • 同步加载模块: CommonJS模块是同步加载的,即在需要的地方使用require函数加载模块,并立即获取其导出内容。
  • 导出方式: 使用module.exports导出模块内容,或者通过给exports对象添加属性来导出单个成员

姿势一:module.exports集中导出

// 导出
// utils.js
module.exports = {
  add: (a, b) => a + b,
  subtract: (a, b) => a - b
};

// 导入
// app.js
const { add, subtract } = require('./utils');
console.log(add(5, 3)); // 输出: 8
console.log(subtract(5, 3)); // 输出: 2

姿势二:exports逐个导出

// 导出
// utils.js
exports.add = (a, b) => a + b;
exports.subtract = (a, b) => a - b;

// 导入
// app.js
const { add, subtract } = require('./utils');
console.log(add(5, 3)); // 输出: 8
console.log(subtract(5, 3)); // 输出: 2

姿势三:直接赋值给module.exports

// 导出
// utils.js
module.exports = (a, b) => a + b;

// 导入
// app.js
const add = require('./utils');
console.log(add(5, 3)); // 输出: 8

ESM规范

ESMECMAScript官方引入的模块化规范,它在现代浏览器和Nodejs中都得到了广泛支持。它的主要特点包括:

  • 异步加载模块: ESM模块是异步加载的,模块需要使用import语句加载,可以在运行时动态加载模块。
  • 导出方式: 使用export关键字导出模块内容,可以导出多个成员,也可以起别名。

姿势一:export命名导出

使用export关键字,可以命名导出一个或多个成员,这些成员在导入时需要使用相应的名称来访问。

// 导出
// utils.js
export function add(a, b) {
  return a + b;
}

export function subtract(a, b) {
  return a - b;
}

// 导入
// app.js
import { add, subtract } from './utils';
console.log(add(5, 3)); // 输出: 8
console.log(subtract(5, 3)); // 输出: 2

姿势二:export default默认导出

使用export default关键字,可以导出一个默认成员,一个模块只能有一个默认导出。

// 导出
// utils.js
const add = (a, b) => a + b;
export default add;

// 导入
import add from './utils';
console.log(add(5, 3)); // 输出: 8

在导入时,可以自定义默认导出成员的名称:

// 导入并重命名
import myAddFunction from './utils';
console.log(myAddFunction(5, 3)); // 输出: 8

姿势三:export + export default 混合导出

在一个模块中,既可以有命名导出,又可以有默认导出。

// 导出
// utils.js
export function add(a, b) {
  return a + b;
}

function subtract(a, b) {
  return a - b;
}

export default subtract;

// 导入
// app.js
import subtract, { add } from './utils';
console.log(add(5, 3)); // 输出: 8
console.log(subtract(5, 3)); // 输出: 2

姿势四:重新导出

可以在一个模块中重新导出另一个模块的成员,方便从一个中心模块导出所有需要的内容。

// 导出一
// mathUtils.js
export function add(a, b) {
  return a + b;
}

// 导出二
// utils.js
export function subtract(a, b) {
  return a - b;
}

export function multiply(a, b) {
  return a * b;
}

// 引入后重新集中导出
// main.js
export { add } from './mathUtils';
export { subtract, multiply } from './utils';

// 导入
// app.js
import { add, subtract, multiply } from './main';
console.log(add(5, 3)); // 输出: 8
console.log(subtract(5, 3)); // 输出: 2
console.log(multiply(5, 3)); // 输出: 15

姿势五:全部导入

使用import * as <alias>语法,可以将一个模块的所有导出成员导入为一个对象。

// 导出
// utils.js
export function add(a, b) {
  return a + b;
}

export function subtract(a, b) {
  return a - b;
}

// 导入
// app.js
import * as math from './utils';
console.log(math.add(5, 3)); // 输出: 8
console.log(math.subtract(5, 3)); // 输出: 2

这些是ESM规范中常见的导出方式,通过灵活运用它们,可以更好地组织和管理模块化的JavaScript代码。

异同点对比

加载方式

  • CommonJS使用同步加载模块,适合服务器端,但在浏览器中可能会造成阻塞。
  • ESM使用异步加载模块,更适合浏览器环境,可以提高性能。

静态分析

  • ESM可以在静态分析时确定模块依赖关系,这使得一些优化和工具更易实现。
  • CommonJS在运行时才能确定依赖,限制了某些优化的可能性。

动态导入

  • ESM允许使用import()函数在运行时动态加载模块,以支持按需加载。
  • CommonJS没有原生的动态导入方式,尽管在Nodejs中可以使用实验性的import()函数。

应用场景

  • CommonJS适用于服务器端应用,特别是在Nodejs环境中,可以方便地管理模块依赖。
  • ESM适用于浏览器和现代Nodejs应用,尤其在前端项目中,可以利用浏览器的异步加载能力

注意事项

  • 当在Nodejs中使用ESM规范时,需要在脚本文件中使用.mjs扩展名,并在package.json中设置"type": "module"
  • ESM中的模块路径解析相对于当前文件,而CommonJS中相对于包含模块的目录。
  • ESM中的导入和导出是静态的,不能根据条件进行导入或导出,而CommonJS可以在运行时根据条件加载模块。

总结

CommonJSESM规范各有优势,选择取决于应用的环境和需求。

Nodejs环境中,可以根据项目需求选择使用哪种规范,而在现代的浏览器环境中,ESM规范更加适用。

熟悉这两种规范的异同以及各自的应用场景,将有助于开发者更好地进行模块化开发并提高代码质量和可维护性。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
AMD(Asynchronous Module Definition)和 CMD(Common Module Definition)是两种常见的JavaScript模块化规范,而CommonJS则是另一种常见的JavaScript模块化规范。 AMD和CMD都是异步加载JavaScript模块的规范,可以在页面加载完毕后再异步加载JavaScript模块。这样可以加快页面的加载速度,提高用户体验。 AMD规范是由RequireJS推广和实现的,它的特点是定义模块时采用的是函数式的语法。AMD模块通过define()函数定义,模块的依赖通过数组参数来定义: ``` //定义模块 define(['module1', 'module2'], function(module1, module2) { //模块代码 }); ``` CMD规范是由SeaJS推广和实现的,它的特点是定义模块时采用的是对象式的语法。CMD模块通过define()函数定义,模块的依赖通过函数参数来定义: ``` //定义模块 define(function(require, exports, module) { //引入依赖模块 var module1 = require('module1'); var module2 = require('module2'); //模块代码 }); ``` CommonJS规范则是由Node.js推广和实现的,它的特点是采用同步加载JavaScript模块的方式。CommonJS模块通过module.exports和require()函数来定义和引入模块: ``` //定义模块 module.exports = { //模块代码 }; //引入模块 var module1 = require('module1'); ``` 总的来说,AMD和CMD主要用于浏览器端的JavaScript模块化开发,而CommonJS主要用于服务器端的JavaScript模块化开发。在实际开发中,可以根据自己的需求选择合适的模块化规范

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CreatorRay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值