JavaScript 实用封装技巧
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!
7. 深/浅拷贝(知识补充)
7.1 浅拷贝
只能复制对象的第一层属性,嵌套对象仍然是引用
const obj1 = { a: 1, b: 2 }
// 方式1
const obj2 = { ...obj1 }
// 方式2
Object.assign({}, obj1)
7.2 深拷贝
能复制深层属性,嵌套对象不受影响,各自独立
const obj1 = { a: 1, b: { c: 2 } };
// 方式1(性能一般,无兼容性)
const obj2 = JSON.parse(JSON.stringify(obj1));
// 方式2(性能好,Chrome 97+ 版本支持)
const obj2 = structuredClone(obj);

浙公网安备 33010602011771号