函数式编程思想与JavaScript实践


函数式编程思想与JavaScript实践

函数式编程(FP)是一种编程范式,它强调使用纯函数、不可变数据和函数组合来构建程序。JavaScript作为一门多范式语言,非常适合实践函数式编程。本文将介绍函数式编程的核心思想和JavaScript中的实践方法。

一、核心概念

// 纯函数 - 相同输入总是产生相同输出,无副作用
function add(a, b) { return a + b; }  // 纯函数
var count = 0;
function increment() { return ++count; }  // 非纯函数

// 不可变数据
var user = { name: "张三", age: 25 };
// 不推荐:直接修改
user.age = 26;

// 推荐:创建新对象
var updatedUser = Object.assign({}, user, { age: 26 });
// 或使用展开运算符
var updatedUser2 = { ...user, age: 26 };

// 数组不可变操作
var items = [1, 2, 3];
var newItems = [...items, 4];        // 添加
var filtered = items.filter(function(x) { return x !== 2; }); // 删除
var mapped = items.map(function(x) { return x * 2; });  // 转换

二、函数组合

// compose - 从右到左执行
function compose() {
    var fns = Array.from(arguments);
    return function(x) {
        return fns.reduceRight(function(acc, fn) {
            return fn(acc);
        }, x);
    };
}

// pipe - 从左到右执行
function pipe() {
    var fns = Array.from(arguments);
    return function(x) {
        return fns.reduce(function(acc, fn) {
            return fn(acc);
        }, x);
    };
}

// 使用示例
var add10 = function(x) { return x + 10; };
var multiply2 = function(x) { return x * 2; };
var subtract3 = function(x) { return x - 3; };

var transform = compose(subtract3, multiply2, add10);
console.log(transform(5));  // (5+10)*2-3 = 27

var transform2 = pipe(add10, multiply2, subtract3);
console.log(transform2(5));  // 同样27

三、柯里化与偏应用

// 柯里化 - 将多参函数转为一系列单参函数
function curry(fn) {
    return function curried() {
        var args = Array.from(arguments);
        if (args.length >= fn.length) {
            return fn.apply(null, args);
        }
        return function() {
            var moreArgs = Array.from(arguments);
            return curried.apply(null, args.concat(moreArgs));
        };
    };
}

var add = curry(function(a, b, c) { return a + b + c; });
add(1)(2)(3);    // 6
add(1, 2)(3);    // 6
add(1)(2, 3);    // 6

// 实际应用:创建可复用的过滤器
var filter = curry(function(predicate, array) {
    return array.filter(predicate);
});

var getAdults = filter(function(p) { return p.age >= 18; });
var getSeniors = filter(function(p) { return p.age >= 60; });

四、实战:数据处理管道

// 使用函数式风格处理数据
var users = [
    { name: "张三", age: 25, active: true, score: 85 },
    { name: "李四", age: 30, active: false, score: 72 },
    { name: "王五", age: 28, active: true, score: 91 },
    { name: "赵六", age: 35, active: true, score: 68 },
];

// 需求:获取活跃用户的名字,按分数降序排列
var result = pipe(
    function(users) { return users.filter(function(u) { return u.active; }); },
    function(users) { return users.sort(function(a, b) { return b.score - a.score; }); },
    function(users) { return users.map(function(u) { return u.name; }); }
)(users);
// ["王五", "张三"]

函数式编程不是要完全替代面向对象编程,而是提供了另一种思考问题的方式。在JavaScript中,可以灵活地混合使用多种范式。掌握函数式编程的核心思想,可以让你写出更简洁、更可测试、更易维护的代码。


0.053553s