柯里化的概念大家应该都清楚, 就是将一个接受多个参数的函数转化为接受单一参数的函数的技术.
源代码位于 https://github.com/llh911001/mostly-adequate-guide-chinese/blob/master/code/part1_exercises/support.js
柯里化函数:
- function inspect(x) {
- return (typeof x === 'function') ? inspectFn(x) :inspectArgs(x);
- }
- function inspectFn(f) {
- return (f.name) ? f.name : f.toString();
- }
- function inspectArgs(args) {
- Array.prototype.slice.call(arguments, 0);
- return [].slice.call(args, 0).reduce(function(acc, x){
- return acc += inspect(x);
- }, '(') + ')';
- }
- function curry(fx) {
- // 函数的 length 属性返回函数必须传入的参数个数
- var arity = fx.length;
- return function f1() {
- var args = Array.prototype.slice.call(arguments, 0);
- // 参数个数满足的处理
- if (args.length>= arity) {
- return fx.apply(null, args);
- }
- else {
- // 参数个数不满足的处理
- var f2 = function f2() {
- var args2 = Array.prototype.slice.call(arguments, 0);
- return f1.apply(null, args.concat(args2));
- }
- f2.toString = function() {
- return inspectFn(fx) + inspectArgs(args);
- }
- return f2;
- }
- };
- }
其中 f2.toString 的实现是会报错的, 我已经向作者提交了 PR, 这段无关紧要, 可以跳过不看这个 fs.toString 的实现. 很显然实现 curry 函数的核心就是判断参数个数, 然后各种使用 apply 函数.
接下来就可以体验 curry 的好处:
- add = curry(function(x, y) {
- return x + y;
- });
- const add5 = add(5);
- ad5(4)
- // 9
这只是一个非常小的例子, 源代码还有很多例子:
- add = curry(function(x, y) {
- return x + y;
- });
- match = curry(function(what, x) {
- return x.match(what);
- });
- replace = curry(function(what, replacement, x) {
- return x.replace(what, replacement);
- });
- filter = curry(function(f, xs) {
- return xs.filter(f);
- });
- map = curry(function map(f, xs) {
- return xs.map(f);
- });
- reduce = curry(function(f, a, xs) {
- return xs.reduce(f, a);
- });
- split = curry(function(what, x) {
- return x.split(what);
- });
- join = curry(function(what, x) {
- return x.join(what);
- });
在这里我们可以看到, 所有的数据参数都作为了最后一个参数, 很明显这样在使用时的好处就在于, 这可以成为一种预加载函数函数.
非常明显的在于这样柯里化处理函数, 可以让这些函数成为底层部署的函数.
来源: https://juejin.im/post/5afa6fbf6fb9a07ace5903c2