全解析 ESM 模块语法,出去还是进来都由你说了算

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 模块语法是ES6的一个重要特性,它的出现让JavaScript的模块化编程成为了可能。在JavaScript中可以直接使用import和export关键字来导入和导出模块。

模块语法是ES6的一个重要特性,它的出现让JavaScript的模块化编程成为了可能。

JavaScript中可以直接使用importexport关键字来导入和导出模块,但是这种语法并不是ES6的标准,而是ESMECMAScript Module)模块语法的一部分。

虽然导入和导出单个模块的语法非常简单,但是还有许多其他的方式,让你可以使用ESM模块语法来导入和导出模块。

ESM 模块语法

ESM模块语法很简单,它只有两个关键字:importexport

export

export关键字用来导出模块,每个模块都有一个默认导出,可以使用export default关键字来导出。

// 导出一个变量
const name = '田八';
export default name;

这种导出方式可以导出任何类型的数据,包括基本数据类型、对象、函数等。

但是必须得先定义变量,然后再导出,不能在导出的过程中定义变量。

// 错误的导出方式
export default const name = '田八';

对于函数和类的声明,可以无需定义变量,直接导出。

// 导出一个函数
export default function Hello () {
   
  console.log('hello world');
};

// 导出一个类
export default class Hello {
   
  constructor () {
   
    console.log('hello world');
  }
}

对于字面量类型的数据,可以直接导出。

// 导出一个对象
export default {
   
  name: '田八',
  age: 18
};

// 导出一个数组
export default [1, 2, 3, 4, 5];

// 导出一个字符串
export default 'hello world';

// 导出一个数字
export default 123;

命名导出

任何变量都可以在创建时使用export关键字来导出,这种导出方式叫做命名导出。

// 导出一个变量
export const name = '田八';

// 导出一个函数
export function Hello () {
   
  console.log('hello world');
};

// 导出一个类
export class Hello {
   
  constructor () {
   
    console.log('hello world');
  }
}

如果想要导出多个变量,可以使用export关键字,然后在花括号中写上变量名。

// 导出多个变量
const name = '田八';
const age = 18;

export {
    name, age };

如果对导出的变量名不满意,可以使用as关键字来重命名。

// 重命名导出的变量
const name = '田八';
const age = 18;

export {
    
  name as username, // 重命名为 username
  age // 不重命名
};

导出所有

如果想要导出一个模块中的所有变量,通常我们都是像下面这样写的:

import module from './module.js';

// 导出所有变量
export {
   
  ...module
}

其实有一种更简单的方式,就是使用export * from关键字。

// 导出所有变量
export * from './module.js';

这种方式将会导出module.js模块中的所有变量,但是不会导出module.js模块中的默认导出,因为一个模块只能有一个默认导出。

不过export也提供了一种方式来导出其他模块的默认导出:

// 导出其他模块的默认导出
export {
    default } from './module.js';

也可以选择性的导出其他模块的不同变量:

// 导出其他模块的不同变量
export {
    name, age } from './module.js';

同样的,也可以使用as关键字来重命名导出的变量。

// 重命名导出的变量
export {
    name as username, age, default as module } from './module.js';

// 导出其他模块的所有变量,并重命名
export * as module from './module.js';

import

import关键字用来导入模块,通常情况下是直接导入模块中的默认导出。

// 导入模块中的默认导出
import module from './module.js';

如果想同时导入模块中的默认导出和其他变量,可以在花括号中写上变量名。

// 导入模块中的默认导出和其他变量
import module, {
    name, age } from './module.js';

如果想要导入模块中的所有变量,可以使用import * as关键字。

// 导入模块中的所有变量
import * as module from './module.js';

这样就可以通过module对象来访问模块中的所有变量了。

命名导入

和命名导出一样,任何变量都可以在创建时使用import关键字来导入,这种导入方式叫做命名导入。

// 命名导入
import {
    name, age } from './module.js';

也可以使用as关键字来重命名导入的变量。

// 重命名导入的变量
import {
    name as username, age } from './module.js';

还可以混用命名导入和默认导入。

// 混用命名导入和默认导入
import module, {
    name, age } from './module.js';

上面的代码中,module就是默认导入,nameage就是命名导入。

同时,还可以不导入任何变量,只是执行模块中的代码。

// 只执行模块中的代码
import './module.js';

这样做的好处是可以在模块中执行一些初始化代码,比如在模块中注册全局变量,这种方式称为import for side effects(副作用导入)

动态导入

import关键字是静态的,也就是说,它必须在模块的顶层使用,不能在函数或者if语句中使用,或者其他代码块中使用。

// 错误的写法
function loadModule() {
   
  import './module.js';
}

if (true) {
   
  import './module.js';
}

{
   
  import './module.js';
}

上面的代码中,import关键字都是错误的,因为它们都不是模块的顶层。

为了解决这个问题,ES2018引入了import()函数,它可以在任何地方使用,只要是在模块中就可以。

// 正确的写法
function loadModule() {
   
  import('./module.js');
}

if (true) {
   
  import('./module.js');
}

{
   
  import('./module.js');
}

因为ES模块是异步加载的,所以import()函数返回一个Promise对象。

import('./module.js').then(module => {
   
  // ...
});

如果没有找到模块,import()函数会抛出一个错误,所以注意捕获异常。

import('./module.js').catch(err => {
   
  // ...
});

// 或者

try {
   
  await import('./module.js');
} catch (err) {
   
  // ...
}

import()函数可以用在任何地方,不仅仅是模块。

总结

ES模块是JavaScript模块的标准,它的设计目的是为了取代CommonJS模块,成为浏览器和服务器通用的模块解决方案。

最后请记住,导出和静态导入只能在模块的顶层使用,不能在函数或者if语句,或者任何代码块中使用,而动态导入可以在任何地方使用。

目录
相关文章
|
2月前
|
XML 数据格式 开发者
解析数据的Beautiful Soup 模块(一)
解析数据的Beautiful Soup 模块(一)
75 0
|
2月前
|
前端开发 Python
解析数据的Beautiful Soup 模块(二)
解析数据的Beautiful Soup 模块(二)
25 1
|
3月前
|
编解码 开发工具 UED
QT Widgets模块源码解析与实践
【9月更文挑战第20天】Qt Widgets 模块是 Qt 开发中至关重要的部分,提供了丰富的 GUI 组件,如按钮、文本框等,并支持布局管理、事件处理和窗口管理。这些组件基于信号与槽机制,实现灵活交互。通过对源码的解析及实践应用,可深入了解其类结构、布局管理和事件处理机制,掌握创建复杂 UI 界面的方法,提升开发效率和用户体验。
203 13
|
2月前
|
JSON 前端开发 JavaScript
前端模块打包器的深度解析
【10月更文挑战第13天】前端模块打包器的深度解析
|
2月前
|
缓存 前端开发 JavaScript
Webpack技术深度解析:模块打包与性能优化
【10月更文挑战第13天】Webpack技术深度解析:模块打包与性能优化
|
2月前
|
JSON API 开发者
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
23 0
|
2月前
|
移动开发 网络协议 C语言
详解 httptools 模块,一个 HTTP 解析器
详解 httptools 模块,一个 HTTP 解析器
46 0
|
4月前
|
缓存 前端开发 JavaScript
Webpack 模块解析:打包原理、构造形式、扣代码补参数和全局导出
Webpack 模块解析:打包原理、构造形式、扣代码补参数和全局导出
221 1
|
4月前
|
算法 JavaScript 前端开发
国标非对称加密:RSA算法、非对称特征、js还原、jsencrypt和rsa模块解析
国标非对称加密:RSA算法、非对称特征、js还原、jsencrypt和rsa模块解析
341 1
|
4月前
|
算法 JavaScript 前端开发
对称加密算法解析:DES、AES及其在`pycryptodome` 和 `crypto-js` 模块中的应用
对称加密算法解析:DES、AES及其在`pycryptodome` 和 `crypto-js` 模块中的应用
212 1

推荐镜像

更多