梳理过程联想到的函数柯里化

函数柯里化网上的解释是:柯里化(Currying),又称部分求值(Partial Evaluation),是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

我的理解是,柯里化就是分步执行逻辑,传入参数进去会执行此次调用的逻辑且返回下次逻辑调用的函数,这样的方式能够是使我们一连串的逻辑分布执行完毕,甚至是在第一步执行完毕之后执行很多其他的代码逻辑之后,再接着执行下一步逻辑

柯里化极简例子
var add = function(x) {
    return function(y) {
        return x + y;
    };
};
console.log(add(1)(1)); // 第一步逻辑执行完毕之后立即执行第二步:输出2
var add1 = add(1);//执行第一步逻辑
........//执行很多其他的逻辑
console.log(add1(1)); // //执行第二步逻辑:输出2

这个例子有的一讲,我们会发现一个问题,就是说,我们柯里化函数其实用到了一个核心思想,就是闭包,闭包的作用能使我们固定一些参数,可以是普通参数,也可以是函数的传递被我们固化不不再改变

柯里化的特点
  • 1.参数复用
  • 2.提高适用性(函数复用)
  • 3.延迟执行
参数的复用

参数的复用其实在我们的极简例子里已经表现出来了,我们第一步传递的x就不会改变了,不然第二步的时候x+y是找不到x值的,我们用更明显的例子来突出,参数复用

// 正常封装check函数进行字符串正则匹配
function check(reg, txt) {
    return reg.test(txt)
}
check(/\d+/g, 'test')        //false
check(/[a-z]+/g, 'test')     //true
// 使用柯里化函数进行字符串正则匹配
function curryingCheck(reg) {
    return function (txt) {
        return reg.test(txt)
    }
}
var hasNumber = curryingCheck(/\d+/g)
var hasLetter = curryingCheck(/[a-z]+/g)
hasNumber('test1')      // true
hasNumber('testtest')   // false
hasLetter('21212')      // false

以我们的正则匹配来举例柯里化,我们传递的正则属性,是会被第一次调用时候传递进去且在后续使用中不会改变的参数

提高适用性

这里其实用通俗的话来讲就是减少冗余代码,避免反复传递函数参数,其实也是用闭包的原来来实现的

function curryAdapt(fn) {
    var outAgrs = Array.prototype.slice.call(arguments, 1)
    return function () {
        var inArgs = Array.prototype.slice.call(arguments, 0)
        return fn.apply(this, outAgrs.concat(inArgs))
    }
}

function triple(x) {
    return x * 3
}

function map(fn, arr) {
    return arr.map(fn)
}

map(triple, [1, 2, 3])  // [3, 6, 9]
map(triple, [2, 4])     // [6, 12]

var tripleMap = curryAdapt(map, triple)

tripleMap([1, 2, 3])    // [3, 6, 9]
tripleMap([2, 4])       // [6, 12]

这里我们重点解释一下curryAdapt这个柯里化函数,在第一步调用的时候,也就是var tripleMap = curryAdapt(map, triple)的时候,我们传递了一个map函数和一个triple函数,其实网上的这个例子写的太笼统,逻辑实际上是,fn(实际是map)这个第一个函数写在function curryAdapt(fn)中,其实已经是把fn(实际是map)进行了闭包处理,然后又通过处理arguments,取出第二个参数(下标为1),其实也就是取出了triple,这两个一块都给闭包处理了,然后进入下边的返回函数,也就是第二步,第二部进行了参数的接收,也就是tripleMap([1, 2, 3])的时候的数组参数通过arguments下标为0取出参数,把参数进行fn(triple,[1,2,3])的调用了,concat只是为了合并triple和数组,形成一个arguments传递给fn函数,那这个curryAdapt调用之后因为第一次传递的map, triple都已经被缓存了,所以后续就不需要再传递任何参数了

延迟执行

这个延迟执行其实没什么可说的,因为延迟执行也就是一步一步的执行,不管网上说的是惰性处理还是延迟执行,都是一步步调用的意思,调用一步走一步,调用一步走一步,也就算是延迟执行了,或者说第一步做好准备工作,等到第二步真正调用的时候才会执行

Function.prototype.bind = function (context) {
    var _this = this
    var args = Array.prototype.slice.call(arguments, 1)
    return function() {
        return _this.apply(context, args)
    }
}

函数柯里化其实跟高阶函数高阶组件都是有些关系的,是很重要的基础,高阶函数的定义是说,接收其它函数作为参数的函数就称之为高阶函数,高阶组件的定义是说,传递一个组件,返回一个外包组件,这两种定义看起来跟函数柯里化是不是很相似啊,不急,回头我就梳理

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值