JavaScript 函数柯里化(Currying)

67 阅读2分钟

JavaScript 函数柯里化(Currying)

函数柯里化是一种将多参数函数转换为一系列单参数函数的技术。它通过部分应用函数参数来创建新的函数。

基本概念

柯里化的基本形式是将 f(a, b, c) 转换为 f(a)(b)(c)。

// 普通函数
function add(a, b, c) {
  return a + b + c;
}

// 柯里化版本
function curriedAdd(a) {
  return function(b) {
    return function(c) {
      return a + b + c;
    }
  }
}

add(1, 2, 3);      // 6
curriedAdd(1)(2)(3); // 6

实现柯里化的通用方法

function curry(fn) {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn.apply(this, args);
    } else {
      return function(...args2) {
        return curried.apply(this, args.concat(args2));
      }
    }
  };
}

// 使用示例
const curriedAdd = curry(add);
curriedAdd(1)(2)(3); // 6

应用场景

1. 小程序中的应用

  • 参数预配置: 在小程序中,可以预先配置一些通用参数
// 请求API的柯里化版本
const request = curry(function(url, method, data) {
  return wx.request({ url, method, data });
});

const get = request('https://api.example.com')('GET');
const post = request('https://api.example.com')('POST');

// 使用预配置的方法
get({ id: 123 }); // 发起GET请求
post({ name: 'John' }); // 发起POST请求
  • 事件处理: 预置事件处理函数的参数
const handleEvent = curry(function(eventName, component, event) {
  // 处理事件
});

const handleTap = handleEvent('tap');
const handleInput = handleEvent('input');

// 在组件中使用
handleTap(this)(event);

2. 后台管理系统中的应用

  • 权限校验: 创建有权限校验的函数
const checkPermission = curry(function(permission, user, action) {
  if (user.permissions.includes(permission)) {
    action();
  } else {
    console.log('无权限');
  }
});

const checkAdmin = checkPermission('admin');
const checkEditor = checkPermission('editor');

// 使用
checkAdmin(currentUser)(() => {
  // 只有管理员能执行的操作
});
  • 表单验证: 创建可复用的验证器
在这里插入代码片const validate = curry(function(rule, value) {
  return rule.test(value);
});

const validateEmail = validate(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
const validatePhone = validate(/^1[3-9]\d{9}$/);

// 使用
validateEmail('test@example.com'); // true
validatePhone('13800138000'); // true
  • API调用: 创建特定资源的CRUD函数
const resourceAPI = curry(function(baseUrl, resource, action, data) {
  return axios[action](`${baseUrl}/${resource}`, data);
});

const api = resourceAPI('https://api.example.com');
const userAPI = api('user');

// 使用
userAPI('get')({ id: 1 }); // 获取用户
userAPI('post')({ name: 'John' }); // 创建用户

柯里化的优势

  1. 参数复用: 可以固定部分参数,生成更具体的函数

  2. 延迟执行: 可以分步传入参数,在需要时才执行

  3. 函数组合: 便于进行函数组合,创建更复杂的功能

  4. 提高代码复用性: 通过部分应用创建可复用的函数变体

注意事项

  1. 柯里化会增加一定的性能开销(创建多个嵌套函数)
  2. 不是所有场景都适合柯里化,过度使用可能使代码难以理解
  3. 在需要处理可变参数函数时,柯里化实现会变得复杂