博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript 函数式编程---柯里化
阅读量:6259 次
发布时间:2019-06-22

本文共 2645 字,大约阅读时间需要 8 分钟。

1、一些术语

1.1 一元函数

只接受一个参数的函数称为一元函数

const identity = (x) => x复制代码

1.2 二元函数

接受两个参数的函数

const add = (x,y) => x + y复制代码

1.3 变参函数

接受可变数量参数的函数

// es5 function variadic(a){     console.log(a)     console.log(arguments) } // es6 const variadic = (a, ...variadic) => {     console.log(a)     console.log(variadic) }复制代码

2、什么是柯里化?

柯里化就是把一个多参数函数转换为一个嵌套的一元函数的过程。


呵呵,定义看似简单易懂。但还是让人感觉镜中花,水中月。摸不透柯里化的本质。不要急,看官们。让我们先从简单的二元函数add柯里化开始。

2.1 二元函数柯里化

const addCurried = x => y => x + y// 其实就是闭包function addCurried (x){    return function (y){        return x + y    }}addCurried(4)(3)  // 7复制代码

上面是手动地把接受二元函数add转换为含有嵌套的一元的函数。下面展示如何把该处理过程转换为一个名为curry的方法

// es5const curry = (fn){    return function (firstParam){        return function (secondParam){            return fn(firstParam, secondParam)        }    }}// es6let curry = fn => firstParam => secondParam => fn(firstParam, secondParam)复制代码

至此,对于函数柯里化,我们应该揭开了TA神秘的面纱。 但是大多数我们写的函数都是变参的。直接看下面变参函数柯里化

2.2 变参函数柯里化

2.2.1 简单变参函数柯里化
let curry = (fn) => {    if(typeof fn !== 'function'){        throw Error ('参数必须是函数')    }        return function curriedFn(...args){        return fn.apply(null,args)    }}复制代码

如果我们有个multiply函数

// es 6const multiply = (x,y,z)=> x*y*z复制代码

我们可以通过以下方式使用2.2中的curry函数

curry(multiply)(1,2,3) // 6复制代码

下面我们看看,curry是如何运行的。 我们在curry函数里添加了如下代码:

return function curriedFn(...args){    return fn.apply(null,args)}复制代码

返回函数是一个变参函数,它返回了传入args并通过apply调用函数的结果

fn.apply(null, args)复制代码

通过curry(multiply)(1,2,3),args将会指向[1,2,3],由于我们调用了fnapply,等价于:

multiply(1,2,3)复制代码

通过2.2 部分我们实现了变参函数的柯里化,接下来我们实现把多参函数转换为一元函数的curry函数,就如函数柯里化的定义一样。

2.2.2 转换为嵌套的一元函数的curry函数
let curry = (fn)=>{    if(typeof fn !== 'function'){        throw Error('参数必须是函数')    }        return function curriedFn(...args){        if(args.length < fn.length){            return function(){                return curriedFn.apply(null,args.concat([].slice.call(arguments)))            }        }        return fn.apply(null args)    }}复制代码

和之前的curry函数相比我们添加了

if(args.length < fn.length){    return function(){        return curriedFn.apply(null,args.concat([].slice.call(arguments)))    }}复制代码

让我们逐句理解在这段代码中发生了什么

args.length < fn.length复制代码

这行代码是检查通过...args传入的参数长度是否小于函数fn参数列表的长度。如果是,就进入if代码块,如果不是,就如之前一样调用整个函数fn。 一旦进入if代码块,就使用apply函数递归地调用curriedFn函数:

curriedFn.apply(null,args.concat([].slice.call(arguments)))复制代码

此代码片段中:

args.concat([].slice.call(arguments))复制代码

非常重要,我们使用concat函数连接每次传入的参数,并递归地调用curriedFn。由于我们将所有传入的参数组合并递归调用,终将

if(args.length < fn.length)复制代码

条件失败,即参数列表长度args和函数参数的长度fn.length相等。程序将调用整个函数fn

return fn.apply(null args)复制代码

这将产生函数的完整的结果。

好了,函数柯里化就说到这了。 噗。。。感觉写的不好,大佬们请多多关照

转载于:https://juejin.im/post/5bee59d4e51d457c042c20fd

你可能感兴趣的文章
流和文件
查看>>
iOS:UIMapView地图视图控件的简单使用
查看>>
关于Python的3张图
查看>>
作IFRAME于iOS您的设备上支持滚动
查看>>
后台数据库优化——板机
查看>>
C++ redirect input
查看>>
linux_sound_alsa_Android+alsa音频系统中的几个问题
查看>>
IOS Core Image之二
查看>>
python---__getattr__\__setattr_重载'.'操作
查看>>
VMware克隆虚拟机后网络不能正常使用的解决方法
查看>>
android平台TextView使用ImageSpan画廊GIF图像
查看>>
Android开发之ListView-SimpleAdapter的使用
查看>>
App.config提示错误“配置系统未能初始化”
查看>>
Angular - - ngChange、ngChecked、ngClick、ngDblclick
查看>>
JAVA学习第五十九课 — 网络编程概述
查看>>
远程共享文件夹
查看>>
convert2utf8withbom
查看>>
Codeforces Round #336 (Div. 2)A. Saitama Destroys Hotel 水题
查看>>
poj2752 Seek the Name, Seek the Fame(next数组的运用)
查看>>
pgpgin|pgpgout|pswpin|pswpout意义与差异
查看>>