我看到一个奇怪的函数,看起来像这样:
const x = (a) => (b) => a + b;
console.log(x(1)(2))
输出是 3,我知道这是一个返回函数的函数,并且 a 和 b 都在同一范围内,但我的问题是:
通过这个闭包,你可以获得一个具有常量值的函数,以便稍后添加。
- 这在现实生活中如何使用?
您可以将返回的函数用于数组的映射。
- 不使用具有 2 个参数的函数并使用它(对于单行函数)有什么好处?
这是一种更干净、更实用的方法。
const
x = a => b => a + b,
add5 = x(5);
console.log([1, 2, 3].map(add5));
让我们给这个函数起一个更好的名字:
const add = (a) => (b) => a + b
然后你可以写
[1, 2, 3, 4] .map (add (5)) //=> [6, 7, 8, 9]
哪个读起来更好
[1, 2, 3, 4] .map ((n) => 5 + n) //=> [6, 7, 8, 9]
这在一系列
.then()
调用 Promises 中非常方便:
return fetchList (param)
.then (map (add (5)))
.then (filter (lessThan (8)))
.then (average)
(这当然需要柯里化函数
add
、lessThan
、map
和filter
,以及一些简单的average
函数。)
将此与
进行比较 return fetchList (param)
.then (xs => xs.map (x => add (5, x)))
.then (xs => xs.filter (x => lessThan (8, x)))
.then (average)
请注意,
average
在这两个版本中的作用相同的原因是它
采用单个参数。 柯里化的一个要点是将函数转变为采用单个参数的函数。 它使某种风格的编码更容易执行。
Nina 给出了很好的答案。我将提供另一个更高级的示例,其中此类闭包对代码的清晰度有很大帮助。让我们将函数组合成一个前缀检查器,如下所示,然后根据需要多次重复使用它:
//given a word, check if a string s starts with this word
const literal = word => s => s && s.startsWith(word);
//allow to combine 2 literals with OR
const either = (p1, p2) => s => p1(s) || p2(s);
//allow to combine N literals
const any = (...parsers) => parsers.reduce(either);
//create a parser
const check = any(literal('cat'),literal('dog'),literal('cow'));
console.log('cat: ' + check('cat'));
console.log('dog: ' + check('dog is smart'));
console.log('cow: ' + check('cow 123'));
console.log('banana: ' + check('banana'));
实际上,它是一个简化的解析器组合器(不,还不是单子)。扩展这种方法,您可以为自己的编程语言创建解析器,并且它将是可维护且快速的。