本文详细解析 ES6 模块系统的核心机制,涵盖命名导出与默认导出的区别、export 与 import 的具体语法、重命名技巧以及模块加载特性。通过对比 CommonJS 与 AMD,结合代码示例说明如何正确导出变量、函数及类,并解决导入时的作用域与语法糖问题,帮助开发者掌握现代 JavaScript 模块化管理。
引言
近期研读基于 Vue 框架开发的程序时,意识到自身前端技术储备已滞后多年。当前 JavaScript 程序中广泛存在各类模块的导入与导出机制,其语法初看与 Python 相似,仅是将 from 和 import 关键词的顺序颠倒。深入分析后发现,JavaScript 模块机制与 Python 仍有显著差异:导入模块的前提是该模块必须包含导出内容,且导出方式分为默认导出和命名导出两种,处理起来相对繁琐。因此,本文旨在汇总所有 export 导出形式及其对应的 import 导入用法。
ES6 模块基本特点
ES6 在语言标准层面实现了模块功能,确立了其作为浏览器和服务器通用模块解决方案的地位,完全具备取代 CommonJS 和 AMD 规范的能力。其基本特点如下:
- 每个模块仅加载一次,每个 JavaScript 文件仅执行一次;若后续再次加载同一目录下的相同文件,系统将直接从内存中读取结果;
- 模块内部声明的变量均为局部变量,不会污染全局作用域;
- 模块内部的变量或函数可通过 export 关键字导出;
- 一个模块可以导入其他模块的功能。
模块功能主要由两个命令构成:export 和 import。export 命令用于规定模块的对外接口,import 命令用于引入其他模块提供的功能;
一个模块即是一个独立的文件,该文件内部的所有变量在外部无法直接获取。若希望外部能够读取模块内部的某个变量,必须使用 export 关键字输出该变量;
var year = '2018';
var month = 'Febuary';
export {year, month};
export 导出模块
export 导出模块
export 语法声明用于导出函数、对象或指定文件(模块)的原始值。模块导出包含两种方式:命名式导出(Named Exports)和默认导出(Default Exports)。每个模块可以有多个命名式导出,但默认导出每个模块仅允许一个。
命名式导出
命名式导出
模块可以通过 export 前缀关键词声明导出对象,导出的对象可以是多个。这些导出对象通过名称进行区分,这种机制被称为命名式导出。
export { func }; // 导出一个已定义的函数func
export const foo = Math.sqrt(100); // 导出一个常量
我们可以使用 * 和 from 关键字来实现模块的继承:
export * from 'base_module';
模块导出时,可以指定具体的导出成员。导出成员可视为类中的公有成员,而未导出的成员则相当于类中的私有成员:
var name = 'Kevin的居酒屋';
var domain = 'http://coffee.toast.com';
export {name, domain}; // 相当于导出{name:name,domain:domain}
在模块导出时,我们可以使用 as 关键字对导出成员进行重命名,上述导出示例可改写为:
export {name as siteName, domain}
注意以下语法错误:
export 1;
var a = 100;
export a;
export 在导出接口时,必须与模块内部的变量具有一一对应的关系。直接导出数字(如 export 1)没有任何意义,且在 import 时无法找到对应变量。虽然 export a 看似成立,但 a 的值若为数字,根本无法完成解构,因此必须写成 export {a} 的形式。即使 a 被赋值为函数,也不建议使用上述形式导出,因为主流编码风格建议模块末尾统一使用 export 导出所有接口,如前述示例所示。
默认导出
默认导出
默认导出也被称为定义式导出。命名式导出可导出多个值,但在 import 引用时需使用相同名称来引用相应值。默认导出仅导出一个单一值,该值可以是函数、类或其他类型,这使得模块在 import 导入时引用更为简便。
export default function() {}; // 导出一个函数
export default class(){}; // 导出一个类
默认导出可理解为另一种形式的命名导出,即默认导出相当于使用了 default 名称的命名导出。
下面两种导出方式是等价的:
const D = 123;
export default D;
export { D as default };
使用名称导出一个模块时:
// "my-module.js" 模块
function cube(x) {
return x * x * x;
}
const foo = Math.PI + Math.SQRT2;
export { cube, foo };
在另一个模块(JS 文件)中,我们可以像下面这样引用:
import { cube, foo } from 'my-module';
console.log(cube(3));
console.log(foo);
使用默认导出一个模块时:
// "my-module.js"模块
export default function (x) {
return x * x * x;
}
在另一个模块中,我们可以像下面这样引用,相比命名导出,使用更为简单:
import cube from 'my-module';
console.log(cube(3)); // 27
import 导入模块
import 导入模块
import 语法声明用于从已导出的模块或脚本中导入函数、对象或指定文件(模块)的原始值。import 模块导入与 export 模块导出功能相对应,同样存在两种模块导入方式:命名式导入(Named Imports)和默认导入(Default Imports)。
注意事项:import 语句必须放在文件的最开始,且前面不允许有其他逻辑代码,这与其他所有编程语言的导入风格一致。
命名导入
命名导入
我们可以通过指定名称将导入成员插入到当前作用域中。可以导入单个成员或多个成员:
注意,花括号里面的变量必须与 export 后面的变量一一对应。
import {myMember} from "my-module";
import {foo, bar} from "my-module";
通过 * 符号,我们可以导入模块中的全部属性和方法。当导入模块全部导出内容时,即将导出模块('my-module.js')所有的导出绑定内容,插入到当前模块('myModule')的作用域中:
import * as myModule from "my-module";
默认导入与 default 关键字
默认导入
在模块导出时,可能会存在默认导出。同样地,在导入时可以使用 import 指令导入这些默认值。直接导入默认值:
import defaultName from "my-module";
import myDefault, {foo, bar} from "my-module"; // 指定成员导入和默认导入
default 关键字
// my-module.js
export default function() {}
// 等效于:
function func() {};
export {func as default};
在 import 的时候,可以这样用:
import a from './my-module';
// 等效于,或者说就是下面这种写法的简写
import {default as a} from './my-module';
这个语法糖的好处是,import 的时候可以省去 {}。
简单来说,如果 import 时你发现某个变量没有花括号括起来(没有 * 号),那么你在脑海中应该把它还原成有花括号的 {default as ...} 语法,所以 import $,{each,map} from 'jquery'; import 后面第一个 $ 是 {default as $} 的替代写法。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。