由链式调用再探函数柯里化

前言

函数柯里化并不是JS的一个特性,而是一种处理函数的模式,我第一次接触这个概念还是在准备面试复习JS的时候,然而由于之前对函数柯里化不熟悉,复习也就没有完全理解,导致面试时候关于函数柯里化的题只要稍微有变动,就能卡得我一脸懵逼。“一知半解”可是面试中的大忌,于是我打算——再探函数柯里化。

回顾概念

所谓函数柯里化,就是以函数闭包为核心,实现函数参数不确定的情况下函数能链式调用并且每一次调用都能取得正确的值,这个值并不会立即返回,事实上,每次调用返回的依然是一个可调用的函数。

这样的函数整个过程实际上就是:逐步接受参数-不立即输出结果-返回一个接受参数的函数。因此这样的函数也称作“部分计算函数”、“懒累积计算函数(公司大佬取得名字,挺形象)”,

延迟计算和参数复用

先来看个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
let currying = (fn) =>  {
let arr = [];

let next = (...args) => {
if (args.length > 0) {
arr.push(...args);
// 实现链式调用
return next;
} else {
return fn(...arr);
}
}
return next;
}
let add = currying((...args) => {
let sum = 0;
for (let item of args) {
sum += item;
}
return sum;
})
add(1);
add(2, 3);
add(4);
let sum = add(5)();
console.log(sum); // 15

上述例子我们可以很清楚的看到延迟计算,复用参数这两个柯里化函数的特点:

  • 直到最终传入一个空参数引发了计算之前,调用add函数并没有发生计算,只是将传入的参数放到一个数组中保存起来——延迟计算
  • 了解函数闭包的特性的人应该知道,函数闭包内部如果用到了外部函数内的变量,那么这个变量不会随着外部函数执行完销毁而消失,而是会保留在内存中。每次调用add保存下来的参数都得以在内存中保留以供后面使用——参数复用

函数执行的时机

对于函数执行的时机,上文的方法是判断传入的参数个数,当没有参数的时候就执行

但是,也可以通过重写Function的toString来优雅地返回函数调用的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
function add(...args) {
const flag = [...args];
const modifyFun = function(...args) {
flag.push(...args);
return modifyFun;
}
modifyFun.valueOf = modifyFun.toString = function() {
return flag.reduce(function(res, cur) {
return cur + res;
})
}
return modifyFun;
}

这样我们每次需要读取函数的值时都会调用toString方法,而计算的过程就在toString函数里面执行,即不破坏延迟执行,又可以优雅地返回结果

但是对于上述代码,柯里化和加法操作被耦合在了一起,我们可以像第一个例子那样稍作改动,将功能抽离出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function tool(fn) {
const flag = [];
const modifyFun = function(...args) {
flag.push(...args);
return modifyFun;
}
modifyFun.valueOf = modifyFun.toString = function() {
return fn(...flag)
}
return modifyFun;
}
let add = tool(function(...args) {
return [...args].reduce(function(res, cur) {
return cur * res;
})
})
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2015-2021 AURORA_ZXH
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信