0
点赞
收藏
分享

微信扫一扫

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

JakietYu 2022-03-12 阅读 96

柯里化极简例子

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)
    }
}
举报

相关推荐

0 条评论