柯里化函数思想

柯里化这个词一看就感觉高大上,实际当你了解后才发现其实就是高阶函数的一个特殊用法

柯里化是什么?

柯里化 Currying ,就是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

做个简单示例:

// 普通的add函数
function add(x, y) {
    return x + y
}
// Currying后
function curryingAdd(x) {
    return function (y) {
        return x + y
    }
}
add(1, 2)           // 3
curryingAdd(1)(2)   // 3
为什要柯里化?有什么好处和作用?
1. 参数复用
// 正常正则验证字符串 reg.test(txt)

// 函数封装后
function check(reg, txt) {
    return reg.test(txt)
}

check(/\d+/g, 'test')       //false
check(/[a-z]+/g, 'test')    //true

// Currying后
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

上面的示例是一个正则的校验,正常来说直接调用check函数就可以了,但是如果我有很多地方都要校验是否有数字,其实就是需要将第一个参数reg进行复用,这样别的地方就能够直接调用hasNumber,hasLetter等函数,让参数能够复用,调用起来也更方便。

2.提前确认
var on = (function() {
    if (document.addEventListener) {
        return function(element, event, handler) {
            if (element && event && handler) {
                element.addEventListener(event, handler, false);
            }
        };
    } else {
        return function(element, event, handler) {
            if (element && event && handler) {
                element.attachEvent('on' + event, handler);
            }
        };
    }
})();

//换一种写法可能比较好理解一点,上面就是把isSupport这个参数给先确定下来了
var on = function(isSupport, element, event, handler) {
    isSupport = isSupport || document.addEventListener;
    if (isSupport) {
        return element.addEventListener(event, handler, false);
    } else {
        return element.attachEvent('on' + event, handler);
    }

我们在做项目的过程中,封装一些dom操作可以说再常见不过,上面第一种写法也是比较常见,但是我们看看第二种写法,它相对一第一种写法就是自执行然后返回一个新的函数,这样其实就是提前确定了会走哪一个方法,避免每次都进行判断。

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

像我们js中经常使用的bind,实现的机制就是Currying.

面试题:编写一个ADD函数满足如下需求

add(1);       //1
add(1)(2);    //3
add(1)(2)(3); //6
add(1)(2,3);  //6
add(1,2)(3);  //6
add(1,2,3);   //6
方法一:
思路:1、参数未定,调用次数未定 2、返回结果必须是个函数
        function add(...outerArgs){
            // outerArgs 已经拿到了第一次执行的参数合集
            // 重写 add 函数
            add = function(...innerArgs){
                // innerArgs 下次函数执行的参数合集
                // outerArgs 和 innerArgs 合并就是每次执行函数和参数合用来求和
                
                outerArgs = outerArgs.concat(innerArgs)

                // 返回结果是一个函数
                return add
            }
            // 重写toString 方法 为求和 在alert时就可以得到和
            add.toString = function(){
                return outerArgs.reduce((x,y)=> x+y)
            }
            // 返回结果是一个函数
            return add
        }

        alert(add(1))
方法二:
      function currying(anonymous,length){
            return function add(...args){
                if(args.length >= length){
                    return anonymous(...args)
                }
                return currying(anonymous.bind(null,...args),length - args.length)
            }
        }

        let add = currying(function anonymous(...args){
            return args.reduce((x,y)=>x+y)
        },3)

        console.log(add(1,2)(3))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值