柯里化再谈

来源:互联网 发布:mac下载工具推荐 编辑:程序博客网 时间:2024/06/08 16:17


柯里化思想:

柯里化其实本身是固定一个可以预期的参数,并返回一个特定的函数,处理批特定的需求。这增加了函数的适用性,但同时也降低了函数的适用范围。

举个栗子:

实现一个函数,运算结果可以满足如下预期结果:

    add(1)(2) // 3    add(1, 2, 3)(10) // 16    add(1)(2)(3)(4)(5) // 15

刚好这个功能要实现的就是柯里化的思想。把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回 能接受余下的参数且返回结果的新函数的技术。在这里新函数的功能就是相加。

柯里化起到了参数复用的作用。

function add () {        //将argument转换成数组        var args = Array.prototype.slice.call(arguments);        var fn = function () {            //拼接多次调用的参数为数组            var arg_fn = Array.prototype.slice.call(arguments);            //递归调用add            return add.apply(null, args.concat(arg_fn));        }        //最后一次返回fn时,自动调用valueOf        fn.valueOf = function () {            return args.reduce(function(a, b) {                return a + b;            })        }        return fn;    }

扩展知识,用到了js的reduce方法。

再举个栗子

已知 fn 为一个预定义函数,实现函数 curryIt,调用之后满足如下条件:
1、返回一个函数 a,a 的 length 属性值为 1(即显式声明 a 接收一个参数)
2、调用 a 之后,返回一个函数 b, b 的 length 属性值为 1
3、调用 b 之后,返回一个函数 c, c 的 length 属性值为 1
4、调用 c 之后,返回的结果与调用 fn 的返回值一致
5、fn 的参数依次为函数 a, b, c 的调用参数

输入

var fn = function (a, b, c) {return a + b + c}; curryIt(fn)(1)(2)(3);

输出

6
思路:

简单理解题目意思,就是指,我们将预定义的函数的参数逐一传入到curryIt中,当参数全部传入之后,就执行预定义函数。于是,我们首先要获得预定义函数的参数个数fn.length,然后声明一个空数组去存放这些参数。返回一个匿名函数接收参数并执行,当参数个数小于fn.length,则再次返回该匿名函数,继续接收参数并执行,直至参数个数等于fn.length。最后,调用apply执行预定义函数。

柯里化起到了延迟执行的作用。

function curryIt(fn) {  var args = Array.prototype.slice.call(arguments,1);  return args.length<fn.length?function(a){    console.log([fn].concat(args,a));      return curryIt.apply(curryIt,[fn].concat(args,a));    }:fn.apply(null,args);}


还有固定易变因素的作用。

柯里化特性决定了它这应用场景。提前把易变因素,传参固定下来,生成一个更明确的应用函数。最典型的代表应用,是bind函数用以固定this这个易变对象。