一、基础函数封装
1. 基本函数定义
// 函数声明
function calculateArea(width, height) {
return width * height;
}
// 函数表达式
const calculateArea = function(width, height) {
return width * height;
};
// 箭头函数(ES6+)
const calculateArea = (width, height) => width * height;
2. 参数处理
// 默认参数
function greet(name = 'Guest', greeting = 'Hello') {
return `${greeting}, ${name}!`;
}
// 剩余参数
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
// 解构参数
function printUser({name, age, email}) {
console.log(`Name: ${name}, Age: ${age}, Email: ${email}`);
}
二、高级封装模式
1. 模块模式
// 立即执行函数表达式(IIFE)
const Calculator = (function() {
// 私有变量
let memory = 0;
// 私有函数
function validateNumber(num) {
return typeof num === 'number' && !isNaN(num);
}
// 公共API
return {
add: function(a, b) {
if (!validateNumber(a) || !validateNumber(b)) {
throw new Error('Invalid numbers');
}
return a + b;
},
storeInMemory: function(value) {
memory = value;
},
getMemory: function() {
return memory;
}
};
})();
2. 工厂函数
function createUser(name, email) {
// 私有变量
let loginCount = 0;
// 返回对象
return {
name,
email,
login() {
loginCount++;
console.log(`${this.name} logged in ${loginCount} times`);
return this;
},
getLoginCount() {
return loginCount;
}
};
}
const user = createUser('Alice', 'alice@example.com');
三、ES6+ 类封装
class User {
// 私有字段(ES2022)
#password;
constructor(name, email, password) {
this.name = name;
this.email = email;
this.#password = password;
this.loginCount = 0;
}
// 公共方法
login(inputPassword) {
if (this.#validatePassword(inputPassword)) {
this.loginCount++;
console.log(`${this.name} logged in successfully`);
return true;
}
return false;
}
// 私有方法
#validatePassword(inputPassword) {
return inputPassword === this.#password;
}
// 静态方法
static createAdmin(name, email) {
const admin = new User(name, email, 'admin123');
admin.isAdmin = true;
return admin;
}
}
四、函数封装最佳实践
1. 单一职责原则
// ❌ 不好的做法
function processUser(user) {
// 验证、保存、发送邮件都在一个函数
validateUser(user);
saveToDatabase(user);
sendWelcomeEmail(user);
}
// ✅ 好的做法
function processUser(user) {
validateUser(user);
persistUser(user);
notifyUser(user);
}
2. 纯函数
// 纯函数:相同输入总是得到相同输出,无副作用
function calculateTotal(items, taxRate) {
const subtotal = items.reduce((sum, item) => sum + item.price, 0);
return subtotal * (1 + taxRate);
}
3. 柯里化和函数组合
// 柯里化
const multiply = a => b => a * b;
const double = multiply(2);
console.log(double(5)); // 10
// 函数组合
const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x);
const addTax = price => price * 1.1;
const applyDiscount = price => price * 0.9;
const calculateFinalPrice = compose(addTax, applyDiscount);
五、实际封装示例
1. 数据获取函数
async function fetchData(url, options = {}) {
const defaultOptions = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
timeout: 5000,
};
const config = { ...defaultOptions, ...options };
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), config.timeout);
const response = await fetch(url, {
...config,
signal: controller.signal
});
clearTimeout(timeoutId);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return await response.json();
} catch (error) {
console.error('Fetch error:', error);
throw error;
}
}
2. 缓存函数
function memoize(fn) {
const cache = new Map();
return function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
console.log('Returning cached result');
return cache.get(key);
}
const result = fn.apply(this, args);
cache.set(key, result);
return result;
};
}
// 使用示例
const expensiveCalculation = memoize(function(n) {
console.log('Calculating...');
return n * 2;
});
六、注意事项
避免全局污染:使用模块作用域
错误处理:适当添加try-catch和参数验证
文档化:使用JSDoc注释
测试:为封装的函数编写测试
性能考虑:避免不必要的闭包和内存泄漏
通过良好的函数封装,可以提高代码的可读性、可维护性和可复用性,是现代JavaScript开发的核心技能之一。