js 函数柯里化(Currying)

JavaScript 函数柯里化(Currying)

在计算机科学中,柯里化(Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

从一道面试题谈谈函数柯里化从一道面试题谈谈函数柯里化

题目:使用 js 实现 add(1)(2)(3)(4) 返回 10

函数柯里化要求多个参数转为单一参数,所以相当于

1
2
3
4
5
6
7
8
9
function add() {
return Array.from(arguments);
}
// 调用:add(1, 2, 3, 4) => [1, 2, 3, 4]
// 转换为下面形式
function addCurrying() {
// do something
}
// 调用:addCurrying(1)(2)(3)(4) => [1, 2, 3, 4]

闭包拿参数

闭包:定义在一个函数内部的函数,静态保存所有了父级作用域的内部函数。所以每次的值可以保存住,到了最后可以全部访问到

所以,我们先来一个闭包来拿取到所有参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var add = function (value) {
var result = [];
result.push(value);
// _add 函数就是一个闭包,拿取到父级作用域的值,因为_add函数已获取到父级数据,所以父级一直存在,没有释放
var _add = function (value2) {
result.push(value);
return _add;
};
// 此方法调用返回数组
_add.getResult = function () {
return result;
};
return _add;
};

这样通过上面函数就可以实现基本的柯里化要求

执行:

1
2
3
4
5
6
7
8
9
// addCurrying(1)(2)(3)(4).getResult => [1, 2, 3, 4]
// addCurrying(1)(2)(3)(4)
// =>
/*
ƒ (value2) {
result.push(value);
return _add;
}
*/

重写内置函数返回结果

上面的代码虽然已经获取到所有的参数,但是返回结果并没有自动返回,而是需要调用函数才返回。

并且由于不知道参数长度,也就无法通过参数数组长度来及时返回结果。

那么有什么方法可以解决呢?🤔

当然有了,在 js 中函数是有原型链的,所以每个函数都继承了基本的一些方法。

当你定义一个函数后,你如果打印时只输入函数名,并不执行,则函数内部信息就被打印出来。

那么我们可以重写这个方法,来在结束后执行。

函数的 toString 方法可以打印函数体,所以我们改造下,让 toString 返回结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//首先我们需要一个入口函数进行基本处理
var add = function (value) {
//定义一个保存所有传入的参数的数组
var result = [];
// 将第一个传入的参数放置进去
result.push(value);
// 定义函数 _add 引用result变量,使其保持不被销毁掉
var _add = function (subValue) {
// 将参数push进入result中去
result.push(subValue);
// 返回函数 _add 进行下次一调用
return _add;
};
// 将原生自带的toString 进行重写
_add.toString = function () {
return result;
};
// 返回 _add 函数进行下次调用
return _add;
};

执行结果

  • add(1) => [1]
  • add(1)(2) => [1,2]
  • add(1)(2)(3) => [1,2,3]

结束

通过上面的研究,解决一个函数柯里化问题。

-------文章到此结束  感谢您的阅读-------