JavaScript高级函数式编程:Composition与Currying实战指南
一、函数组合(Composition)核心原理
构建可维护的数据处理管道:
// 基础compose实现
const compose = (...fns) =>
fns.reduce((f, g) => (...args) => f(g(...args)));
// 实用函数
const toUpperCase = str => str.toUpperCase();
const exclaim = str => `${str}!`;
const repeat = str => `${str} ${str}`;
// 组合使用
const dramatic = compose(exclaim, repeat, toUpperCase);
console.log(dramatic('hello')); // 输出: "HELLO HELLO!"
// 更复杂的组合示例
const cleanText = str => str.trim();
const removeSpecialChars = str => str.replace(/[^ws]/g, '');
const splitWords = str => str.split(/s+/);
const filterShortWords = words => words.filter(w => w.length > 3);
const processText = compose(
filterShortWords,
splitWords,
removeSpecialChars,
cleanText
);
console.log(processText(' Hello, world! This is functional programming. '));
// 输出: ["Hello", "world", "This", "functional", "programming"]
核心价值:声明式编程、代码复用、易于测试、数据流清晰
二、柯里化(Currying)高级应用
1. 自动柯里化实现
// 自动柯里化函数
const curry = (fn, arity = fn.length) => {
return function curried(...args) {
if (args.length >= arity) {
return fn.apply(this, args);
} else {
return (...moreArgs) => curried.apply(this, args.concat(moreArgs));
}
};
};
// 实际应用
const multiply = curry((a, b, c) => a * b * c);
const double = multiply(2);
const triple = double(3);
console.log(triple(4)); // 输出: 24
// 数据库查询示例
const query = curry((db, table, conditions) => {
return db(table).where(conditions);
});
// 部分应用
const queryUsers = query(getDatabase());
const queryActiveUsers = queryUsers('users', { active: true });
// 延迟执行
const results = await queryActiveUsers();
2. 参数占位符技巧
// 带占位符的柯里化
const _ = Symbol('placeholder');
const advancedCurry = (fn, arity = fn.length) => {
return function curried(...args) {
const completeArgs = args.slice(0, arity);
const hasPlaceholder = completeArgs.includes(_);
if (completeArgs.length >= arity && !hasPlaceholder) {
return fn.apply(this, completeArgs);
} else {
return (...moreArgs) => {
const mergedArgs = [];
let argIndex = 0;
for (const arg of completeArgs) {
mergedArgs.push(arg === _ ? moreArgs[argIndex++] : arg);
}
return curried.apply(this, mergedArgs.concat(moreArgs.slice(argIndex)));
};
}
};
};
// 使用示例
const formatMessage = advancedCurry(
(greeting, name, punctuation) => `${greeting}, ${name}${punctuation}`
);
const hello = formatMessage('Hello', _, '!');
console.log(hello('Alice')); // 输出: "Hello, Alice!"
三、React函数式组件实战
1. 高阶组件组合
// 基础高阶组件
const withLogger = Component => props => {
console.log(`Rendering ${Component.name} with props:`, props);
return ;
};
const withAnalytics = Component => props => {
useEffect(() => {
trackPageView(Component.name);
}, []);
return ;
};
// 工具函数
const composeHOCs = (...hocs) => Component =>
hocs.reduceRight((acc, hoc) => hoc(acc), Component);
// 组合使用
const enhance = composeHOCs(
withLogger,
withAnalytics,
withTheme
);
const EnhancedProductCard = enhance(ProductCard);
// 柯里化版本
const withFeatures = features => Component => props => (
);
const withUser = userId => Component => props => {
const [user, setUser] = useState(null);
useEffect(() => {
fetchUser(userId).then(setUser);
}, [userId]);
return user ? : ;
};
// 动态创建组件
const createUserProfile = userId => composeHOCs(
withUser(userId),
withFeatures(['profile', 'settings'])
)(ProfilePage);
四、性能优化策略
1. 记忆化(Memoization)
// 记忆化函数
const memoize = fn => {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn(...args);
cache.set(key, result);
return result;
};
};
// 柯里化记忆函数
const memoizedCurry = fn => {
const curried = curry(fn);
return memoize(curried);
};
// 实际应用
const expensiveCalculation = memoizedCurry((a, b, c) => {
console.log('Computing...');
return a * b * c;
});
const calcWith5 = expensiveCalculation(5);
console.log(calcWith5(2)(3)); // 输出: Computing... 30
console.log(calcWith5(2)(3)); // 输出: 30 (无Computing日志)
2. 惰性求值(Lazy Evaluation)
// 惰性函数链
const lazyChain = (initialValue) => {
const fns = [];
let value = initialValue;
return {
add(fn) {
fns.push(fn);
return this;
},
execute() {
return fns.reduce((acc, fn) => fn(acc), value);
}
};
};
// 使用示例
const result = lazyChain([1, 2, 3, 4, 5])
.add(arr => arr.filter(x => x % 2 === 0))
.add(arr => arr.map(x => x * 2))
.add(arr => arr.reduce((a, b) => a + b, 0))
.execute();
console.log(result); // 输出: 12
五、函数式编程原则
- 纯函数:相同输入总是返回相同输出
- 不可变性:避免数据突变
- 函数优先:将函数作为一等公民
- 组合优于继承:通过组合构建复杂行为
- 声明式风格:关注”做什么”而非”怎么做”