函数柯里化

函数柯里化

比如我们现在有这样一个函数,传入一个学生的学校,专业和名字三个参数。对这三个数据做一点处理然后再输出。
接触函数柯里化之前的都是这样的思想:

	function say(school, academy, name) {
      console.log('我的学校是'+school+',我的专业是'+academy+',我的名字是'+name+'。');
    }

    say('西邮', '计科', '张三'); //我的学校是西邮,我的专业是计科,我的名字是张三。
    say('西邮', '计科', '李四'); //我的学校是西邮,我的专业是计科,我的名字是李四。
    say('西邮', '计科', '王五'); //我的学校是西邮,我的专业是计科,我的名字是王五。

当我们一遍遍的调用这个函数,会发现参数中的前两个是重复的,那我们想有没有什么方法可以让我们只传一次相同的参数呢?

这是我们会想用闭包,做一个函数嵌套,来保存外部函数的参数。

	function say1(school) {
      return function(academy) {
        return function(name) {
          console.log('我的学校是'+school+',我的专业是'+academy+',我的名字是'+name+'。');
        }
      }
    }

这个时候我们的调用say1的话,返回的是一个函数(要传入academy参数,而且内部还返回了一个函数的函数)。所以我们用一个变量取接受这个函数:

	var newSchool = say1('西邮');

而当我们再调用newSchool这个函数时,它的返回值也是一个函数(要传入name参数的函数),我们再声明一个变量来接收这个函数。

	var newAcademy = newSchool('计科');

这样newAcademy的就是一个已经传入前两个参数,等待传入最后一个不同的参数的函数了。那我们就可以这样来打印三组不同的数据了:

	newAcademy('张三'); //我的学校是西邮,我的专业是计科,我的名字是张三。
	newAcademy('李四'); //我的学校是西邮,我的专业是计科,我的名字是李四。
	newAcademy('王五'); //我的学校是西邮,我的专业是计科,我的名字是王五。

因为第一个函数的返回值是一个函数,那我们就可以做这样一个优化(再第一个函数后面再加一个函数执行符号,里面传入对应的参数):

	var newData = say1('西邮')('计科');
	newData('张三');//我的学校是西邮,我的专业是计科,我的名字是张三。
	newData('李四');//我的学校是西邮,我的专业是计科,我的名字是李四。
	newData('王五');//我的学校是西邮,我的专业是计科,我的名字是王五。

这就是函数柯里化。
但是暴露了一个很明显的问题:太麻烦!每次要将函数改写成return嵌套。所以我们现在来封装一个柯里化函数:

	function curry(fn) {
      var len = fn.length;
      return function temp(){
        var agr = [...arguments];
        if(agr.length >= len) {
          return fn(...agr);
        } else {
          return function() {
            return temp(...agr, ...arguments);
          }
        }
      }
    }

主要思想:柯里化函数体里返回了一个收集参数的递归调用的函数一,在这个函数内部:首先,先判断要被柯里化的函数的参数长度是否等于函数一的参数长度,若相等,直接执行要被柯里化的函数(把函数一的参数直接传入)。若小于,将递归调用这个函数一(把新传入的参数和之前传入的参数都传入函数一)。

我们来测试一下:

	var first = curry(say);
	first('西邮')('计科')('张三');//我的学校是西邮,我的专业是计科,我的名字是张三。
	first('西邮')('计科')('李四');//我的学校是西邮,我的专业是计科,我的名字是李四。
	first('西邮')('软件')('王五');//我的学校是西邮,我的专业是软件,我的名字是王五。

当然我们也可用柯里化后的函数进行参数复用,延迟执行等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值