参数复用
- 示例场景:数学函数与配置参数复用:在数学计算或数据处理中,假设有一个通用的函数用于计算两点之间的距离,其公式为$\sqrt{(x_2 - x_1)^2+(y_2 - y_1)^2}$。如果要在多个地方计算二维平面上不同点与一个固定点(例如原点$(0,0)$)的距离,就可以使用函数柯里化。
- 代码示例:
// 原始的计算两点距离的函数 function distance(x1, y1, x2, y2) { return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); } // 柯里化函数 function curry(fn) { return function curried(...args) { if (args.length >= fn.length) { return fn.apply(this, args); } else { return function (...moreArgs) { return curried.apply(this, args.concat(moreArgs)); }; } }; } // 对distance函数进行柯里化 const distanceFromOrigin = curry(distance)(0, 0); // 计算点(3,4)到原点的距离 console.log(distanceFromOrigin(3, 4));
- 在这个例子中,通过柯里化将计算与原点距离的函数
distanceFromOrigin
创建出来,以后每次计算某个点到原点的距离时,就不需要重复传入原点的坐标$(0,0)$,实现了参数复用,提高了代码的简洁性和可读性。
延迟执行与动态函数创建
- 示例场景:事件处理与条件判断后的函数执行:在前端开发的事件处理中,根据用户的操作动态地决定执行的函数。例如,有一个按钮,点击按钮时,根据用户是否登录,执行不同的函数。
- 代码示例:
function createEventHandler(loggedIn, actionIfLoggedIn, actionIfLoggedOut) { return function () { if (loggedIn) { return curry(actionIfLoggedIn)(); } else { return curry(actionIfLoggedOut)(); } }; } function loggedInAction() { console.log("User is logged in and performing an action."); } function loggedOutAction() { console.log("User is logged out and performing an action."); } const buttonClickHandler = createEventHandler(true, loggedInAction, loggedOutAction); // 模拟按钮点击事件 buttonClickHandler();
- 这里,
createEventHandler
函数返回一个新的函数,这个新函数根据用户是否登录的状态,在点击事件发生时,通过柯里化延迟执行对应的loggedInAction
或loggedOutAction
函数。这样可以灵活地根据运行时的条件来决定执行的函数,实现了延迟执行和动态函数创建。
函数组合与管道操作
- 示例场景:数据处理管道与函数组合:在数据处理流程中,例如对一个数据集进行一系列的转换操作,如先过滤数据,再对过滤后的数据进行映射(转换数据格式),最后进行求和操作。
- 代码示例:
// 过滤函数 function filterData(data, predicate) { return data.filter(predicate); } // 映射函数 function mapData(data, mapper) { return data.map(mapper); } // 求和函数 function sumData(data) { return data.reduce((acc, cur) => acc + cur, 0); } // 柯里化函数 function curry(fn) { return function curried(...args) { if (args.length >= fn.length) { return fn.apply(this, args); } else { return function (...moreArgs) { return curried.apply(this, args.concat(moreArgs)); }; } }; } // 柯里化各个函数 const curriedFilter = curry(filterData); const curriedMap = curry(mapData); const curriedSum = curry(sumData); // 组合函数 const dataProcessingPipeline = data => curriedSum(curriedMap(curriedFilter(data, num => num > 5), num => num * 2)); const dataSet = [1, 3, 7, 9, 11]; console.log(dataProcessingPipeline(dataSet));
- 在这个例子中,通过柯里化将
filterData
、mapData
和sumData
函数转换为可以逐步应用的形式,然后组合成一个数据处理管道dataProcessingPipeline
。这样可以方便地构建复杂的数据处理流程,每个函数都可以独立地进行单元测试和复用,并且通过柯里化可以灵活地调整参数的传递顺序和时机,实现函数的组合和管道操作。