JavaScript currying 教程定义了 currying 转换并在实际示例中进行了演示。
柯里化
Currying 是将具有多个参数的函数转换为具有单个参数的一系列嵌套函数。柯里化允许执行函数专业化和组合。
我们可以将fn(a,b,c)
可调用对象转换为fn(a)(b)(c)
。
柯里化函数是高阶函数,它允许我们创建原始函数的专用版本。柯里化的工作归功于闭包,闭包在返回后保留封闭的函数范围。
Lodash 包含_.curry
函数,可以将普通函数转换为柯里化函数。在 Ramda 中,所有函数都是自动柯里化的。
JS curry 基本示例
以下基本示例使用柯里化。
function multiply(a, b, c) { return a * b * c; } function multiply_curried(a) { return function (b) { return function (c) { return a * b * c } } } let res = multiply(1, 2, 3); console.log(res); let mc1 = multiply_curried(1); let mc2 = mc1(2); let res2 = mc2(3); console.log(res2); let res3 = multiply_curried(1)(2)(3); console.log(res3);
我们有普通的multiply
函数,它将三个参数相乘。代码 multiply_curried
使用柯里化来完成乘法。
let res = multiply(1, 2, 3);
这是经典的函数调用;它的所有参数都在圆括号之间传递。
let mc1 = multiply_curried(1); let mc2 = mc1(2); let res2 = mc2(3); console.log(res2);
在柯里化中,函数接受一个参数并返回另一个函数,后者接受下一个参数,直到所有参数都用完。
let res3 = multiply_curried(1)(2)(3);
这是前面代码的简写。
$ node basic.js 6 6 6
JS curry 基础实例二
下一个示例使用箭头函数来创建普通函数和柯里化函数。
let multiply = (a, b, c) => { return a * b * c; } let multiply_curried = (a) => (b) => (c) => { return a * b * c; } let res = multiply(1, 2, 3); console.log(res); let res2 = multiply_curried(1)(2)(3); console.log(res2);
乘法函数使用箭头函数语法重写。
JS 非柯里化
可以取消柯里化函数。
let multiply_curried = (a) => (b) => (c) => { return a * b * c; } let multiply = (a, b, c) => multiply_curried(a)(b)(c); let res = multiply(2,3,4); console.log(res); let res2 = multiply_curried(2)(3)(4); console.log(res2);
该示例将multiply_curried
转换为multiply
函数。
JS curry – 泛型函数
我们创建了一个通用函数来检查单词是否有 n 个字符。
let hasNChars = (n=3) => (word) => word.length === n; let words = ['forest', 'gum', 'pencil', 'wonderful', 'grace', 'table', 'lamp', 'biblical', 'midnight', 'or', 'perseverance', 'adminition', 'redemption', 'dog', 'no']; let res = words.some(hasNChars(2), words); console.log(res); let res2 = words.some(hasNChars, words); console.log(res2);
有一个单词数组。 hasNChars
函数首先获取n
值,然后获取要检查的单词。如果我们不提供 n
值,则使用默认值 3。
let res = words.some(hasNChars(2), words);
使用数组的some
函数,我们检查是否有包含两个字符的单词。
let res2 = words.some(hasNChars, words);
这里我们检查是否有两个字母的单词。
$ node hasnchars.js true true
JS curry – 特殊函数
专用函数派生自更通用的函数。
let greet = (message) => (name) => { return `${message} ${name}!`; } let helloGreet = greet('Hello'); console.log(greet('Good day')('Lucia')); console.log(helloGreet('Peter'));
有一个柯里化的greet
函数。专门的helloGreet
函数派生自greet
函数。
$ node specialized.js Good day Lucia! Hello Peter!
JS curry – 函数组合
函数组合允许组合任意数量的函数来创建一个新函数。
let double = x => x * 2 let triple = x => x * 3 let quadruple = x => x * 4 let pipe = (...funs) => input => funs.reduce( (total, fn) => fn(total), input ) let fun1 = pipe(double) let fun2 = pipe(double, triple) let fun3 = pipe(triple, triple) let fun4 = pipe(double, triple, quadruple) console.log(fun1(2)) console.log(fun2(5)) console.log(fun3(7)) console.log(fun4(9))
pipe
函数采用任意数量的参数 – 函数。组合函数稍后采用函数运行的输入值。要创建pipe
函数,我们使用reduce
函数。阅读 JavaScriptreduce 教程以了解有关 reduce
函数的更多信息。
$ node composing.js 4 30 63 216
Lodash _.curry
Lodash 是一个强大的库,它为常见的编程任务提供实用函数。 _.curry
函数将普通函数变成柯里化函数。
$ npm i lodash
我们需要安装 Lodash 库。
const _ = require("lodash"); function multiply(a, b, c) { return a * b * c; } let curried = _.curry(multiply); let ret = curried(2)(3)(4); console.log(ret);
在示例中,我们将 multiply
函数转换为柯里化版本。
Ramda 自动柯里化
Ramda 是一个面向 JavaScript 程序员的实用函数库。该库专注于不变性和无副作用的功能。 Ramda 函数也会自动柯里化。
$ npm i ramda
我们需要安装 Ramda 库。
const R = require('ramda'); let fn1 = R.add(5); let res = fn1(6); console.log(res); let fn2 = R.divide(100); let res2 = fn2(20); console.log(res2);
我们在R.add
和R.divide
函数中演示了自动柯里化。
$ node auto_curry.js 11 5
JS自定义curry方法
最后,我们创建自定义 curry 方法。
function multiply(a, b, c) { return a * b * c; } function curry(func) { return function curried(...args) { console.log(args); if (args.length >= func.length) { return func.apply(this, args); } else { console.log('calling else'); return function(...args2) { return curried.apply(this, args.concat(args2)); } } }; } let curried = curry(multiply); console.log(curried(1, 2, 3)); console.log(curried(1)(2, 3)); console.log(curried(1)(2)(3));
自定义curry
方法是使用递归创建的。我们还利用展开运算符、apply
函数和函数 length
属性。
length
属性返回函数接收的参数数量。 apply
函数使用给定的 this
值和作为数组提供的参数调用给定函数。
let curried = curry(multiply);
我们使用自定义curry
函数创建了乘法函数的柯里化版本。
console.log(curried(1, 2, 3));
curried
函数仍然可以正常调用。
console.log(curried(1)(2, 3));
在这一行中,我们正在柯里化第一个参数。
console.log(curried(1)(2)(3));
我们柯里化所有三个参数。
$ node mycurry.js [ 1, 2, 3 ] 6 [ 1 ] [ 1, 2, 3 ] 6 [ 1 ] [ 1, 2 ] [ 1, 2, 3 ] 6
在本文中,我们研究了 JavaScript 中的柯里化转换过程。我们还简要提到了 Lodash 和 Ramda 功能库。
列出所有 JavaScript 教程。