模块化是将程序拆分为独立模块的开发方式。
// 模块化的目的:
// 1. 代码组织:将相关功能组织在一起
// 2. 命名空间:避免全局变量污染
// 3. 复用性:模块可以在不同项目中复用
// 4. 可维护性:独立模块更易维护
// 5. 依赖管理:明确模块间的依赖关系
// 无模块化的问题
// 全局污染
var name = "东巴文";
var name = "db-w.cn"; // 覆盖
// 命名冲突
function getData() {}
function getData() {} // 覆盖
// 依赖混乱
// 谁依赖谁?加载顺序?
// 阶段1:全局函数
function foo() {}
function bar() {}
// 阶段2:命名空间
var MyApp = {
foo: function() {},
bar: function() {}
};
// 阶段3:IIFE
var Module = (function() {
var private = "私有";
function privateMethod() {}
return {
public: "公开",
publicMethod: function() {}
};
})();
// 阶段4:模块规范
// CommonJS, AMD, UMD, ES Modules
主要的模块化规范。
// Node.js使用的规范
// 导出
module.exports = {
name: "东巴文",
greet: function() {
return "Hello";
}
};
// 或
exports.name = "东巴文";
exports.greet = function() {
return "Hello";
};
// 导入
const module = require("./module");
console.log(module.name);
// 异步模块定义(浏览器端)
define(["jquery", "underscore"], function($, _) {
return {
name: "东巴文",
init: function() {
$("body").html("Hello");
}
};
});
// 使用
require(["module"], function(module) {
module.init();
});
// 通用模块定义
(function(root, factory) {
if (typeof define === "function" && define.amd) {
// AMD
define([], factory);
} else if (typeof module === "object" && module.exports) {
// CommonJS
module.exports = factory();
} else {
// 全局变量
root.MyModule = factory();
}
}(typeof self !== "undefined" ? self : this, function() {
return {
name: "东巴文",
greet: function() {
return "Hello";
}
};
}));
// ES6模块
// 导出
export const name = "东巴文";
export function greet() {
return "Hello";
}
export default { name, greet };
// 导入
import { name, greet } from "./module.js";
import myModule from "./module.js";
import * as all from "./module.js";
模块化带来的好处。
// 按功能组织代码
// utils.js
export function formatDate(date) {
return date.toLocaleDateString();
}
export function debounce(fn, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
// api.js
import { request } from "./request.js";
export function getUser(id) {
return request(`/api/user/${id}`);
}
export function getPosts(userId) {
return request(`/api/posts/${userId}`);
}
// app.js
import { formatDate } from "./utils.js";
import { getUser, getPosts } from "./api.js";
async function init() {
const user = await getUser(1);
console.log(formatDate(new Date()));
}
// 模块有独立的作用域
// moduleA.js
const name = "东巴文";
export function getName() {
return name;
}
// moduleB.js
const name = "db-w.cn"; // 不冲突
export function getName() {
return name;
}
// app.js
import { getName as getNameA } from "./moduleA.js";
import { getName as getNameB } from "./moduleB.js";
console.log(getNameA()); // 东巴文
console.log(getNameB()); // db-w.cn
// 明确的依赖关系
// userService.js
import { api } from "./api.js";
import { cache } from "./cache.js";
export class UserService {
async getUser(id) {
const cached = cache.get(`user:${id}`);
if (cached) return cached;
const user = await api.get(`/users/${id}`);
cache.set(`user:${id}`, user);
return user;
}
}
// 依赖图
// app.js
// ├── userService.js
// │ ├── api.js
// │ └── cache.js
// └── router.js
设计模块的最佳实践。
// 好的设计:每个模块只做一件事
// formatDate.js
export function formatDate(date) {
return date.toLocaleDateString();
}
// parseDate.js
export function parseDate(str) {
return new Date(str);
}
// 不好的设计:一个模块做太多事
// dateUtils.js
export function formatDate() {}
export function parseDate() {}
export function calculateAge() {}
export function getDaysBetween() {}
// 高内聚:相关功能放在一起
// userValidator.js
export function validateName(name) {
return name.length >= 2;
}
export function validateEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
export function validateAge(age) {
return age >= 0 && age <= 150;
}
// 低耦合:模块间依赖最小化
// 使用依赖注入
export class UserService {
constructor(api) {
this.api = api;
}
async getUser(id) {
return this.api.get(`/users/${id}`);
}
}
// 提供清晰的公共接口
// calculator.js
// 私有函数
function validateInput(a, b) {
if (typeof a !== "number" || typeof b !== "number") {
throw new TypeError("参数必须是数字");
}
}
// 公共接口
export function add(a, b) {
validateInput(a, b);
return a + b;
}
export function subtract(a, b) {
validateInput(a, b);
return a - b;
}
// 默认导出
export default {
add,
subtract
};
常用的模块化构建工具。
// webpack.config.js
module.exports = {
entry: "./src/index.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist")
},
module: {
rules: [
{
test: /\.js$/,
use: "babel-loader"
}
]
}
};
// rollup.config.js
export default {
input: "src/index.js",
output: {
file: "dist/bundle.js",
format: "esm"
}
};
// vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
root: "src",
build: {
outDir: "../dist"
}
});
掌握了模块化概述后,让我们继续学习:
东巴文(db-w.cn) - 让编程学习更简单
🎯 东巴文寄语:模块化是现代JavaScript开发的基石,理解模块化的演变和各种规范有助于更好地组织代码。在 db-w.cn,我们帮你建立模块化思维!