【JavaScript】函数式编程:一文搞懂函数科里化(Currying)~(一)

简介: 【JavaScript】函数式编程:一文搞懂函数科里化(Currying)~(一)

在之前的两篇文章:

我介绍了JS函数式编程中的一些概念及其实践,本文则着重详细、深入介绍里面最常用的技术之一 —— 函数柯里化。

柯里化(Currying)

柯里化(Currying)是一种关于函数的高阶技术,它允许你将一个有多个参数的函数转化为一连串的函数,它返回一个新的函数,等待下一个参数的内联。换句话说,一个函数不是一次接受所有的参数,而是接受第一个参数并返回一个新的函数,该函数接受第二个参数并返回一个新的函数,该函数接受第三个参数,以此类推,直到所有参数都得到满足。

这个概念是以数学家 Haskell Curry 的名字命名的,他在1930年代提出了这个概念。在JavaScript中,Currying 是一个强大的工具,它可以将一个有多个参数的函数转化为一系列嵌套的函数,每个函数只接受一个参数。Currying 帮助你避免多次传递同一个变量,并帮助你创建一个高阶函数。可以提高代码的可重用性、可组合性和可维护性。

在本文中,我们将深入探讨curry,提供全面的解释和例子。

柯里化有两个特点:

  1. 柯里化是一种函数的转换,它是指将一个函数从可调用的 f(a, b, c) 转换为可调用的 f(a)(b)(c)
  2. 柯里化不会调用函数。它只是对函数进行转换。

先来看一个例子,创建一个辅助函数 curry(f),该函数将对两个参数的函数 f 执行柯里化。换句话说,对于两个参数的函数 f(a, b) 执行 curry(f) 会将其转换为以 f(a)(b) 形式运行的函数:

function curry(f) { // curry(f) 执行柯里化转换
  return function(a) {
    return function(b) {
      return f(a, b);
    };
  };
}
// 用法
function sum(a, b) {
  return a + b;
}
let curriedSum = curry(sum);
alert( curriedSum(1)(2) ); // 3

正如你所看到的,实现非常简单:只有两个包装器(wrapper)。

  • curry(func) 的结果就是一个包装器 function(a)
  • 当它被像 curriedSum(1) 这样调用时,它的参数会被保存在词法环境中,然后返回一个新的包装器 function(b)
  • 然后这个包装器被以 2 为参数调用,并且,它将该调用传递给原始的 sum 函数。

柯里化更高级的实现,例如 lodash 库的 _.curry,会返回一个包装器,该包装器允许函数被正常调用或者以部分应用函数(partial)的方式调用:

function sum(a, b) {
  return a + b;
}
let curriedSum = _.curry(sum); // 使用来自 lodash 库的 _.curry
alert( curriedSum(1, 2) ); // 3,仍可正常调用
alert( curriedSum(1)(2) ); // 3,以部分应用函数的方式调用

函数科里化(Currying)是JavaScript中的一个高级特性,它能够将接受多个参数的函数变成一系列只接受部分参数的函数。这种技术在函数式编程中经常使用,并且可以使代码更加灵活和可复用。以下是一个详细的js代码示例,展示了如何实现函数科里化。

// 定义一个普通的函数,它接收两个参数并返回他们的和
function add(x, y) {
  return x + y;
}
// 编写一个curry函数,它可以对任何函数进行科里化
function curry(fn) {
  // 获取除第一个参数外的其他参数
  var args = Array.prototype.slice.call(arguments, 1);
  // 返回一个新函数,如果参数足够执行则调用原来的函数,否则继续科里化
  return function() {
    var newArgs = args.concat(Array.prototype.slice.call(arguments));
    if (newArgs.length >= fn.length) {
      return fn.apply(this, newArgs);
    } else {
      return curry.call(this, fn, ...newArgs);
    }
  };
}
// 使用curry函数对add进行科里化
var curriedAdd = curry(add);
// 调用curriedAdd函数,返回一个新函数
var add1 = curriedAdd(1);
// 继续调用新函数,返回结果2
console.log(add1(1)); // 2
// 另一种调用方式
console.log(curriedAdd(2)(3)); // 5

在上面的代码中,我们首先定义了一个普通的函数add,它接收两个参数并返回他们的和。然后,我们编写了一个名为curry的函数,它接受一个要进行科里化的函数作为第一个参数,并且通过Array.prototype.slice.call(arguments, 1)获取除了第一个参数外的其他参数。

curry函数内部,我们返回了一个新函数,这个新函数如果接收到的参数足够执行,则调用原来的函数。否则,继续使用curry函数对其进行科里化。这个过程通过newArgs变量将之前传入的参数和当前传入的参数合并起来实现。最后,我们通过return curry.call(this, fn, ...newArgs);递归调用curry函数,直到参数足够执行时结束递归调用。

我们使用curry函数对add函数进行科里化,得到一个名为curriedAdd的函数。我们可以使用curriedAdd函数来创建新的函数,例如使用curriedAdd(1)返回一个只需要一个参数的新函数。当我们调用这个新函数时,它会返回一个结果,而不是立即执行。当我们重新调用这个函数,将它的返回值和另一个参数一起传入时,它会再次返回结果,依此类推。

总之,函数科里化是JavaScript中一个非常强大的技术,它可以使代码更加灵活和可复用。在某些特定场景下,使用函数科里化可以简化代码并提高开发效率。

相关文章
|
4月前
|
机器学习/深度学习 JavaScript 前端开发
JS进阶教程:递归函数原理与篇例解析
通过对这些代码示例的学习,我们已经了解了递归的原理以及递归在JS中的应用方法。递归虽然有着理论升华,但弄清它的核心思想并不难。举个随手可见的例子,火影鸣人做的影分身,你看到的都是同一个鸣人,但他们的行为却能在全局产生影响,这不就是递归吗?雾里看花,透过其间你或许已经深入了递归的魅力之中。
193 19
|
6月前
|
JavaScript
JS实现多条件搜索函数
JS封装的多条件搜索
|
8月前
|
JavaScript 前端开发
JavaWeb JavaScript ③ JS的流程控制和函数
通过本文的详细介绍,您可以深入理解JavaScript的流程控制和函数的使用,进而编写出高效、可维护的代码。
179 32
|
7月前
|
JavaScript 前端开发 Java
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
柯里化是一种强大的函数式编程技术,它通过将函数分解为单参数形式,实现了灵活性与可复用性的统一。无论是参数复用、延迟执行,还是函数组合,柯里化都为现代编程提供了极大的便利。 从 Redux 的选择器优化到复杂的数据流处理,再到深度嵌套的函数优化,柯里化在实际开发中展现出了非凡的价值。如果你希望编写更简洁、更优雅的代码,柯里化无疑是一个值得深入学习和实践的工具。从简单的实现到复杂的应用,希望这篇博客能为你揭开柯里化的奥秘,助力你的开发之旅! 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
269 2
|
11月前
|
JavaScript 前端开发
JavaScript中的原型 保姆级文章一文搞懂
本文详细解析了JavaScript中的原型概念,从构造函数、原型对象、`__proto__`属性、`constructor`属性到原型链,层层递进地解释了JavaScript如何通过原型实现继承机制。适合初学者深入理解JS面向对象编程的核心原理。
183 1
JavaScript中的原型 保姆级文章一文搞懂
|
11月前
JS+CSS3文章内容背景黑白切换源码
JS+CSS3文章内容背景黑白切换源码是一款基于JS+CSS3制作的简单网页文章文字内容背景颜色黑白切换效果。
111 0
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
387 5
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的家政平台附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的家政平台附带文章源码部署视频讲解等
221 4
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的宠物援助平台附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的宠物援助平台附带文章源码部署视频讲解等
210 4

热门文章

最新文章