柯里化和工厂函数,在js前端开发中的应用场景

好的!以下是柯里化(Currying)和工厂函数(Factory Function)在 JavaScript 前端开发中的具体应用场景和代码示例:


1. 柯里化(Currying)的应用

柯里化是将一个多参数函数转换为一系列单参数函数的技术,核心目的是复用参数、延迟执行

应用场景 1:参数复用(通用函数定制)

场景:前端中需要多次调用类似逻辑的函数,但部分参数固定。

// 通用请求函数(未柯里化)
function fetchData(baseURL, endpoint, params) {
  return fetch(`${baseURL}/${endpoint}?${new URLSearchParams(params)}`);
}

// 柯里化:固定 baseURL,生成不同 API 的专用函数
function createApiClient(baseURL) {
  return (endpoint) => (params) => 
    fetch(`${baseURL}/${endpoint}?${new URLSearchParams(params)}`);
}

// 创建特定 API 客户端
const githubApi = createApiClient("https://api.github.com");
const getUser = githubApi("users"); // 生成获取用户信息的函数
const getRepo = githubApi("repos"); // 生成获取仓库信息的函数

// 使用
getUser({ username: "torvalds" });
getRepo({ owner: "facebook", repo: "react" });

应用场景 2:事件处理(动态绑定参数)

场景:为列表中的多个按钮绑定不同的事件参数。

// 未柯里化:需要在循环中手动绑定参数
items.forEach((item, index) => {
  button.addEventListener("click", () => handleClick(item.id));
});

// 柯里化:生成专用处理函数
const handleItemClick = (id) => (event) => {
  console.log("Clicked item:", id, event.target);
};

items.forEach((item) => {
  button.addEventListener("click", handleItemClick(item.id));
});

应用场景 3:表单验证(复用校验规则)

场景:验证不同字段的格式是否合法。

// 柯里化:生成不同规则的校验函数
const validate = (pattern) => (value) => pattern.test(value);

// 复用规则
const isEmail = validate(/^\w+@\w+\.\w+$/);
const isPhone = validate(/^\d{11}$/);

// 使用
console.log(isEmail("test@example.com")); // true
console.log(isPhone("13800138000"));     // true

2. 工厂函数(Factory Function)的应用

工厂函数是通过函数批量创建对象的模式,常用于封装对象创建逻辑,隐藏细节。

应用场景 1:动态创建 UI 组件

场景:根据配置生成不同样式的按钮组件。

function createButton(config) {
  const button = document.createElement("button");
  button.textContent = config.text || "Button";
  button.style.backgroundColor = config.color || "#ccc";
  
  // 根据类型绑定不同逻辑
  if (config.type === "submit") {
    button.addEventListener("click", () => {
      config.onSubmit?.();
    });
  } else if (config.type === "cancel") {
    button.addEventListener("click", () => {
      config.onCancel?.();
    });
  }
  
  return button;
}

// 使用工厂创建不同按钮
const submitBtn = createButton({
  text: "提交",
  color: "blue",
  type: "submit",
  onSubmit: () => console.log("数据已提交"),
});

const cancelBtn = createButton({
  text: "取消",
  color: "red",
  type: "cancel",
  onCancel: () => console.log("操作已取消"),
});

应用场景 2:创建数据模型对象

场景:统一处理数据格式,添加默认值。

function createUser({ name, age, role = "user" }) {
  // 私有变量(闭包)
  const createdAt = new Date();

  // 公开方法
  return {
    getName: () => name,
    getAge: () => age,
    getRole: () => role,
    getInfo: () => `${name} (${age}岁, ${role}, 注册于 ${createdAt})`,
  };
}

// 使用工厂创建用户对象
const user1 = createUser({ name: "Alice", age: 25 });
const user2 = createUser({ name: "Bob", age: 30, role: "admin" });

console.log(user1.getInfo()); // "Alice (25岁, user, 注册于 ...)"
console.log(user2.getInfo()); // "Bob (30岁, admin, 注册于 ...)"

应用场景 3:实现缓存机制

场景:为函数调用添加缓存功能,避免重复计算。

function createCachedFetch() {
  const cache = new Map(); // 闭包保存缓存数据

  return async (url) => {
    if (cache.has(url)) {
      console.log("从缓存读取:", url);
      return cache.get(url);
    }
    const response = await fetch(url);
    const data = await response.json();
    cache.set(url, data);
    return data;
  };
}

// 使用工厂创建带缓存的 fetch 函数
const cachedFetch = createCachedFetch();

// 多次调用同一 URL 只会请求一次
cachedFetch("https://api.example.com/data");
cachedFetch("https://api.example.com/data"); // 第二次命中缓存

总结

  • 柯里化
    • 适合参数复用、延迟执行、动态生成函数。
    • 典型场景:事件绑定、API 封装、校验规则复用。
  • 工厂函数
    • 适合隐藏对象创建细节、批量生成对象。
    • 典型场景:UI 组件生成、数据模型封装、缓存机制实现。

两者的核心都依赖闭包,通过函数作用域控制变量生命周期,实现灵活的功能封装。

posted @ 2025-04-11 10:52  张浩伟  阅读(80)  评论(0)    收藏  举报