JavaScript 实用封装技巧
1. 工厂封装
如果需要创建多个结构相似的对象,可以使用工厂函数。
// 创建书籍的工厂函数
function createBook(title, author) {return {title: title,author: author,getDetails() {return `《${this.title}》- 作者: ${this.author}`;},};
}const book1 = createBook("JavaScript 权威指南", "Flanagan");
const book2 = createBook("你不知道的 JavaScript", "Kyle Simpson");console.log(book1.getDetails()); // 输出: 《JavaScript 权威指南》- 作者: Flanagan
2. 闭包封装
有时候,我们不希望外部直接修改对象内部的数据,这时可以利用闭包将状态"藏"起来。
// 封装一个计数器
function createCounter() {let count = 0; // 私有变量,外部无法直接访问return {increment() {count++;console.log(`当前计数: ${count}`);},decrement() {count--;console.log(`当前计数: ${count}`);},getCount() {return count;},};
}const myCounter = createCounter();
myCounter.increment(); // 当前计数: 1
// console.log(myCounter.count); // undefined (无法直接访问)
3. Class 类封装
传统oop方式,更符合面向对象编程习惯。
class Car {constructor(brand, model) {this.brand = brand;this.model = model;this.speed = 0;}// 封装加速行为accelerate(value) {this.speed += value;console.log(`${this.brand} ${this.model} 正在加速,当前时速: ${this.speed}km/h`,);}// 封装刹车行为brake() {this.speed = 0;console.log("车辆已停止。");}
}const myCar = new Car("特斯拉", "Model 3");
myCar.accelerate(50);
myCar.brake();
4. 高阶函数(逻辑委托)
高阶函数是指接收函数作为参数,或者将函数作为返回值的函数。这种封装技巧可以让逻辑变得灵活,适合固定通用逻辑,隔离差异逻辑。
4.1 基础列表处理
// 封装一个通用的列表处理器
function processList(list, callback) {const result = [];for (let i = 0; i < list.length; i++) {result.push(callback(list[i]));}return result;
}const numbers = [1, 2, 3, 4];
const doubled = processList(numbers, (num) => {return num * 2
});
console.log(doubled); // [2, 4, 6, 8]
4.2 异步请求封装 (Fetch)
/*** 封装通用的数据获取函数* @param {string} url 请求地址* @param {function} handleData 处理数据的回调函数*/
async function fetchData(url, handleData) {try {console.log("正在请求数据...");const response = await fetch(url);const data = await response.json();// 封装技巧:不在这里写死处理逻辑,而是调用传入的回调函数handleData(data);} catch (error) {console.error("请求出错:", error);}
}// 使用场景 1:打印用户信息
fetchData("https://api.example.com/user", (user) => {console.log(`获取到用户: ${user.name}`);
});// 使用场景 2:只提取用户的 ID 列表
fetchData("https://api.example.com/users", (users) => {const ids = users.map(u => u.id);console.log("用户 ID 列表:", ids);
});
5. 函数柯里化(预设参数)
将一个多参数函数转换成一系列单参数函数,用来“固定”某些参数。
// 封装一个通用的日志打印器
const createLogger = (type) => (message) => {console.log(`[${type}] ${new Date().toLocaleTimeString()}: ${message}`);
};// 预设好“错误”类型的打印器
const logError = createLogger("错误");
const logInfo = createLogger("信息");logInfo("系统启动成功"); // 输出: [信息] 14:30:05: 系统启动成功
logError("数据库连接失败"); // 输出: [错误] 14:30:10: 数据库连接失败
6. 函数组合
将小函数组合成大函数,每个函数只负责一小块逻辑。
const addExclamation = (str) => `${str}!`;
const toUpper = (str) => str.toUpperCase();// 简单版本
const formatShout = (str) => addExclamation(toUpper(str));// 复杂版本
const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x);
const formatShout = compose(addExclamation, toUpper);console.log(formatShout("hello")); // HELLO!
