柯里化函数

作者: 姜治宇 | 来源:发表于2020-02-10 16:20 被阅读0次

    在解释什么是柯里化函数之前呢,先搞明白另一个概念——高阶函数。
    高阶函数,就是一个函数可以接收另一个函数作为参数,看一个例子:

    function higerFunc(fn){
        return fn()
    }
    higerFunc(function(){
        console.log('hello')
    })
    

    柯里化函数其实就是高阶函数,它可以将函数拆成两步来执行(延期执行),怎么理解呢?
    我们还是看一个例子:

    //普通函数
        function check(reg, txt) {
            return reg.test(txt)
        }
    
        check(/\d+/g, 'test') 
        check(/\d+/g, 'abc123')  
        check(/\d+/g, '789') 
        // Curry化函数,将第一个参数拆分出来复用,第二个参数作为变量。
        function curryingCheck(reg) {
            return function(txt) {
                return reg.test(txt)
            }
        }
    
        var hasNumber = curryingCheck(/\d+/g)
        hasNumber('test')     
        hasNumber('abc123')   
        hasNumber('789')  
    

    大家能看出区别吗?
    柯里化之前的函数,虽然可以一步到位,但正则得写多遍吧,多麻烦啊!而使用了柯里化,虽然拆成两步执行,但可以复用正则表达式,省事不少呢~~
    好,下面看一个柯里化的实际使用场景,大家就能深刻理解柯里化的好处了。
    大家看这样一个需求:
    当点击一个按钮时,如何将额外的数据,传入到这个事件的回调函数中?
    我们试着写一下:

    var dom = document.getElementById('btn')
        function fn(obj){
            console.log(obj)
        }
        var data = {id:1,title:'this is a test'}//这个data如何传入fn?
    
        dom.addEventListener('click',fn,false)//无法传入fn(data)
    

    可以这么改造一下即可:

    dom.addEventListener('click',function(e){
            fn.call(dom,data)
        },false)
    

    这不就行了?且慢!
    如果dom上的click事件挂载了多个,我只想移除特定的某一个,怎么办?

    var dom = document.getElementById('btn')
        function fn(obj){
            console.log(obj)
        }
        var data = {id:1,title:'this is a test'}//这个data,如何传入fn?
        
        dom.addEventListener('click',function(e){
            console.log('第1个click事件') //我只想移除这个click
            fn.call(dom,data)
        },false)
        dom.addEventListener('click',function(e){
            console.log('第2个click事件')//我要保存这个click
            fn.call(dom,e)
    
        },false)
    

    如果用了匿名函数,我们只能将全部click事件移除:

    dom.removeEventListener('click')//dom上挂载的click事件全部被移除了
    

    怎么办呢?
    这就慢慢绕到柯里化上来了,我们可以将fn柯里化一下:

    var dom = document.getElementById('btn')
        function curryFn(obj){
    
            return function(){
                console.log('data:',obj)//内存持有上下文
                console.log('event:',arguments)//内函数的参数
            }
        }
        var data = {id:1,title:'this is a test'}//这个data,如何传入fn?
    
        var clickAction = curryFn(data)
        dom.addEventListener('click',clickAction,false)
        //2s后移除事件
        setTimeout(function(){
            dom.removeEventListener('click',clickAction)
    
        },2000)
    

    我们再将curryFn稍加改造,提升一点逼格:

    function curryFn(){
            var outParams = [].slice.call(arguments) //外层函数的参数,也就是data
            return function(){
                console.log('data:',outParams)
                console.log('event:',arguments)//内层函数的参数,也就是event
            }
        }
    

    相关文章

      网友评论

        本文标题:柯里化函数

        本文链接:https://www.haomeiwen.com/subject/nwunxhtx.html