资讯专栏INFORMATION COLUMN

JavaScript函数柯里化的简单实现

187J3X1 / 2079人阅读

摘要:简单来说,柯里函数就是只接受一个参数的函数,柯里化的起源请参看这篇文章函数式编程入门教程通常来讲,如果三个数求和的函数我们会这样写如果只考虑实现这个函数的柯里化,我们可以这样做观察上面两种不同的写法可以发现,第二种写法其实就是首先把三个参数

简单来说,柯里函数就是只接受一个参数的函数,柯里化的起源请参看这篇文章:函数式编程入门教程
通常来讲,如果三个数求和的函数我们会这样写:

function _sum3(x, y, z) {
    return x + y + z
}

如果只考虑实现这个函数的柯里化,我们可以这样做:

function sum3(x) {
    return function(y) {
        return function(z) {
            return x + y + z
        }
    }
}
console.log(sum3(1)(2)(3)) // 6

观察上面两种不同的写法可以发现,第二种写法其实就是首先把三个参数收集起来,然后到最后再调用第一种写法的函数:

function sum3(x) {
    return function(y) {
        return function(z) {
            return _sum3(x, y, z)
        }
    }
}
console.log(sum3(1)(2)(3)) // 6

所以柯里化的写法只是把常用写法包装了一下,可以使用一个专用的柯里化函数实现这种包装。柯里化函数是一种高阶函数,我们把它命名为curry

function curry(fn) {
    return function(y) {
        return function(z) {
            return fn(x, y, z)
        }
    }
}
var sum3 = curry((x, y, z) => {
    return x + y + z
})
console.log(sum3(1)(2)(3)) // 6

如果有要写一种更加通用的,可以柯里化拥有任意多个参数的函数呢,比如sumN(1)(2)(3)...(N),按照之前的写法,大概是这个样子的:

function curryN(fn) {
    return function(a1) {
        return function(a2) {
            return function(a3) {
                //......
                return function(aN) {
                    return fn(a1, a2, a3, ...aN)
                }
            }
        }
    }
}

很容易想到可以用一个递归函数来简化这种写法,将上面那些看起来相似的函数结构命名为nest,就可以写为:

function nest(fn) {
    return function(x) {
        return nest(fn)
    }
}
function curry(fn) {
    nest(fn)
}

这里缺少一个循环终止的判断,所以nest函数先引入一个新参数i,当i === N时递归终止

function nest(fn, i) {
    return function(x) {
        if (i === N) {
            return fn(...)
        }
        return nest(fn, i + 1)
    }
}
function curry(fn) {
    return nest(fn, 1)
}   

接着,需要一个存放任意多个参数的数组,将这个数组命名为args,然后传入nest函数

function nest(fn, i, args) {
    return function(x) {
        args.push(x)
        if (i === fn.length) {
            return fn(...args)
        }
        return nest(fn, i + 1, args)
    }
}
function curry(fn) {
    const args = []
    return nest(fn, 1, args)
}

最后在添加一个处理0个参数的情况,我们就完成了最终版的柯里化函数

function curry(fn) {
    if (fn.length === 0) {
        return fn
    }
    const args = []
    return nest(fn, 1, args)
}

测试一下,在线demo:

const log1 = curry((x) => console.log(x))
log1(10) // 10
const mul3 = curry((x, y, z) => console.log(x*y*z))
mul3(2)(3)(4) // 24
参考文章

Currying in JS
Currying in JavaScript ES6

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94318.html

相关文章

  • JavaScript函数式编程,真香之组合(一)

    摘要:组合的概念是非常直观的,并不是函数式编程独有的,在我们生活中或者前端开发中处处可见。其实我们函数式编程里面的组合也是类似,函数组合就是一种将已被分解的简单任务组织成复杂的整体过程。在函数式编程的世界中,有这样一种很流行的编程风格。 JavaScript函数式编程,真香之认识函数式编程(一) 该系列文章不是针对前端新手,需要有一定的编程经验,而且了解 JavaScript 里面作用域,闭...

    mengbo 评论0 收藏0
  • 掌握JavaScript函数柯里

    摘要:原文链接和都支持函数的柯里化函数的柯里化还与的函数编程有很大的联系如果你感兴趣的话可以在这些方面多下功夫了解相信收获一定很多看本篇文章需要知道的一些知识点函数部分的闭包高阶函数不完全函数文章后面有对这些知识的简单解释大家可以看看什么是柯里化 原文链接 Haskell和scala都支持函数的柯里化,JavaScript函数的柯里化还与JavaScript的函数编程有很大的联系,如果你感兴...

    DTeam 评论0 收藏0
  • 高阶函数应用 —— 柯里化与反柯里

    摘要:柯里化通用式上面的柯里化函数没涉及到高阶函数,也不具备通用性,无法转换形参个数任意或未知的函数,我们接下来封装一个通用的柯里化转换函数,可以将任意函数转换成柯里化。 showImg(https://segmentfault.com/img/remote/1460000018998373); 阅读原文 前言 在 JavaScript 中,柯里化和反柯里化是高阶函数的一种应用,在这之前...

    wyk1184 评论0 收藏0
  • 柯里化的理解和实现

    摘要:阅读学习专题之函数柯里化函数式编程指南对柯里化的理解很多人对于柯里化的理解仅仅停留在复用参数上。使用柯里化的场景想要实现某个操作逻辑。换句话说,柯里化将输入的函数和参数进行绑定,返回绑定后的函数,返回的函数期待剩余的参数。 阅读学习 JavaScript专题之函数柯里化JS 函数式编程指南 对柯里化的理解 很多人对于柯里化的理解仅仅停留在复用参数上。但我认为函数式编程思想更重要作用的是...

    hsluoyz 评论0 收藏0
  • 「前端面试题系列6」理解函数柯里

    摘要:原题如下写一个方法,当使用下面的语法调用时,能正常工作这道题要考察的,就是对函数柯里化的理解。当参数只有一个的时候,进行柯里化的处理。这其实就是函数柯里化的简单应用。 showImg(https://segmentfault.com/img/bVbopGm?w=620&h=350); 前言 这是前端面试题系列的第 6 篇,你可能错过了前面的篇章,可以在这里找到: ES6 中箭头函数的...

    liaorio 评论0 收藏0

发表评论

0条评论

187J3X1

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<