《解锁 JavaScript 模块化:导入导出实战指南》
各种模块化的导入导出,总是傻傻分不清,碰到就是一团浆糊,就是分不清,今天来整理一下。
CommonJS 模块
导出:
ini
module.exports = {
name: 'John',
age: 25
};
在这个例子中,使用 module.exports
对象来导出模块的内容。您可以将任何数据结构、函数、对象等赋值给 module.exports
,使其能够被其他模块导入和使用。
例如,如果模块中还定义了一个函数:
javascript
function greet() {
console.log('Hello!');
}
module.exports = {
name: 'John',
age: 25,
greet: greet
};
导入:
ini
const person = require('./person');
console.log(person.name);
通过 require('./person')
语句来导入名为 person
的模块。这里的 './person'
表示相对路径。导入后,得到的模块内容被赋值给变量 person
,然后可以通过 person
对象来访问导出的属性和方法。
ES6 模块
导出:
dart
// 导出单个值
export const num = 5;
使用 export
关键字来导出单个常量。
javascript
// 导出函数
export function add(a, b) {
return a + b;
}
直接在函数定义前加上 export
来导出函数。
javascript
// 导出类
export class Person {
constructor(name) {
this.name = name;
}
}
在类定义前加上 export
导出类。
ini
// 导出多个值
const name = 'Alice';
const age = 30;
export { name, age };
先定义多个值,然后使用 export { 变量名 1, 变量名 2 }
的形式来一次性导出多个值。
导入:
javascript
// 导入单个值
import { num } from './module';
通过 import
语句,使用花括号指定要导入的单个导出值。
csharp
// 导入函数
import { add } from './module';
同样使用花括号指定要导入的函数。
javascript
// 导入类
import { Person } from './module';
导入类的方式与导入其他值相同。
javascript
// 导入多个值
import { name, age } from './module';
一次性导入多个值。
AMD 模块(Asynchronous Module Definition) 想象一下 AMD 模块就像是一个工厂。
define
函数就好比是这个工厂的建设规划。
规划里的第一个参数 ['dep1', 'dep2']
,可以理解为这个工厂在生产过程中需要的原材料清单,比如 dep1
是钢材,dep2
是塑料。
第二个参数,也就是那个回调函数,就像是工厂的生产线。生产线上的 dep1
和 dep2
就是已经运到生产线上的钢材和塑料。
在这个生产线上,工厂最终生产出一个产品,也就是通过返回的对象 { name: 'AMD Module' }
,这个产品就是这个工厂向外输出的东西。
而 require
函数呢,就像是一个客户下订单。['module']
就是客户指定要的某个产品,比如就是我们刚刚说的那个工厂生产的产品。
当这个订单完成,也就是模块加载好之后,通过回调函数的参数 module
,客户就拿到了他想要的产品,然后就可以对这个产品进行使用,比如查看、操作等。
再给您举个更具体的例子。比如说我们要做一个游戏,有一个模块是负责生成地图,叫 mapModule
。
它依赖于另一个模块 tileModule
(提供各种地图块)和 enemyModule
(生成敌人)。
define
函数可能像这样:
javascript
define(['tileModule', 'enemyModule'], function(tileModule, enemyModule) {
return {
generateMap: function() {
// 使用 tileModule 和 enemyModule 来生成地图
return '生成的地图数据';
}
};
});
虽然代码内部没有直接写明 mapModule
,但根据 AMD 的约定,这个模块就被默认命名为 mapModule
。
然后在游戏的其他部分,使用这个地图模块时:
javascript
require(['mapModule'], function(mapModule) {
const gameMap = mapModule.generateMap();
// 后续使用生成的地图进行游戏逻辑处理
});
require
函数用于加载模块,并在回调函数中获取加载的模块对象进行使用。
UMD 模块(Universal Module Definition)
javascript
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['dep1', 'dep2'], factory);
} else if (typeof exports === 'object') {
// CommonJS
module.exports = factory(require('dep1'), require('dep2'));
} else {
// 全局变量
root.returnExports = factory(root.dep1, root.dep2);
}
}(this, function (dep1, dep2) {
return {
name: 'UMD Module'
};
}));
UMD 模块的目的是使模块在不同的环境(如 AMD 环境、CommonJS 环境、浏览器全局环境)中都能正确工作。它通过判断当前环境的类型来决定如何导出模块。如果支持 AMD ,就按照 AMD 方式导出;如果支持 CommonJS ,就按照 CommonJS 方式导出;否则,将模块对象赋给全局变量。