JS函数柯里化

在正式聊函数柯里化之前,我这里给大家补充下高阶函数的概念和应用:

1.1、什么是高阶函数?
高阶函数英文叫 Higher-order function,它的定义很简单,就是至少满足下列一个条件的函数:

接受一个或多个函数作为输入
输出一个函数
也就是说高阶函数是对其他函数进行操作的函数,可以将它们作为参数传递,或者是返回它们。 简单来说,高阶函数是一个接收函数作为参数传递或者将函数作为返回值输出的函数。

1.2、高阶函数例子
其实平时开发中经常会用到高阶函数,只是之前你不清楚其概念而已,来看下下面几个函数:

Array.prototype.map
Array.prototype.filter
Array.prototype.reduce
Array.prototype.sort
这三个数组的方法函数就是高阶函数,因为它们都接收一个回调函数作为参数,满足第一个条件

高阶函数其中一个优点就是在某种情况下可以让代码更加简洁,我们就拿map方法来举例,如果不用map这个高阶方法的话,要实现对一个现有数组中每个元素*2的需求

不使用高阶函数:

const arr1 = [1, 2, 3, 4];
const arr2 = [];
for (let i = 0; i < arr1.length; i++) {
arr2.push( arr1[i] * 2);
}
console.log( arr2 );
// [2, 4, 6, 8]
console.log( arr1 );
// [1, 2, 3, 4]

使用map高阶函数:

const arr1 = [1, 2, 3, 4];
const arr2 = arr1.map(item => item * 2);
console.log( arr2 );
// [2, 4, 6, 8]
console.log( arr1 );
// [1, 2, 3, 4]

从上面例子中不难看出用map方法可以轻松实现上述需求,其他两个方法其实也是同样的道理,这里就不多叙述了

二、函数柯里化
2.1、定义
函数柯里化又叫部分求值,维基百科中对柯里化 (Currying) 的定义为:

在数学和计算机科学中,柯里化是一种将使用多个参数的函数转换成一系列使用一个参数的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

用大白话来说就是只传递给函数一部分参数来调用它,让它返回一个新函数去处理剩下的参数

相信部分同学看完这个概念还是有点稀里糊涂,我们来看个简单例子说明下

function url (a,b,c){
return ${a}://www.${b}.${c}
}
const url1 = url('https',"baidu",'com')
console.log(url1) // "https://www.baidu.com"

上面这个url函数接受三个参数,最终函数返回一个完整的url地址,这是普通写法,然后我们来看下函数柯里化后的写法是怎么样的?

function url(a){
return (b)=>{
return (c)=>{
return ${a}://www.${b}.${c}
}
}
}
const AA = url('https') // 他是一个函数
const BB = AA('baidu') // 他是一个函数
const CC = BB('com') // 他是一个函数
console.log(CC) // "https://www.baidu.com"

看到这我们再回过头来看下其概念定义,原先url函数接受多个参数,然后使用了柯里化技术,将其转换成了一系列接收一个参数的函数(url改写后内部就是返回多个接收单一入参的函数),并且返回接受余下的参数(url原先的其他参数b和c现通过其内部返回的其他函数来接收处理了),最终函数柯里化后还是会返回一个新结果的函数(上面例子最终返回的是一个接收参数c返回最终完整结果的函数),现在会不会好理解些了呢

2.2、柯里化的应用(优点)
1、参数复用

还是可以用上面拼接完整url的例子来说明

// DEMO1
//原先的写法
function url (a,b,c){
return ${a}://www.${b}.${c}
}
const url1 = url('https','baidu','com')
const url2 = url('https','jingdong','com')

//柯里化处理后
function url(a){
return (b)=>{
return (c)=>{
return ${a}://www.${b}.${c}
}
}
}
const json1 = url('https');
const url1 = json1('baidu')('com')
const url2 = json1('jindong')('com')

通过对函数柯里化处理后,在生成多个类似url地址时就可以复用相同的部分,不用重复传相同的参数,起到了参数复用的效果,我们还可以再继续巩固下,再来看个例子:

//DEMO2
// 原先正则校验字符串函数每次调用时需要重复传入正则表达式,如果正则表达式很长的话,是不是会显得繁琐
function check(regexp,str){
return regexp.test(str)
}
const result1 = check(/\d+/,'456') // true
const result2 = check(/\d+/,'asd') // false

// 函数柯里化后
function check(regexp){
return (str)=>{
return regexp.test(str)
}
}
const temp = check(/\d+/)
const result1 = temp('456') // true
const result2 = temp('asd') // false

2、延迟调用

js中的bind方法其实底层原理也是应用了柯里化技术,我们来看下代码:

// 下面是bind方法的简易版代码
function bind (ctx,...args){
return ()=>{
return this.apply(ctx,args) // 这里的this指的就是调用bind方法的那个函数
}
}
var name = "windowName"; //全局name
var age = 22; // 全局age
const obj = {name: 'objName',age:11}
function zhangsan (){
return ${this.name}-${this.age}
}
zhangsan() //'windowName-22'
zhangsan.bind(obj) // ƒ zhangsan (){return ${this.name}-${this.age}}
zhangsan.bind(obj)() //'objName-11'

说明:从上面bind方法可以看出,调用bind方法后它只是改变了内部this指向,并返回了一个函数,并没有立即执行该函数,如果想要得到结果,需要再次调用bind方法返回的那个函数才行,所以这点也就说明了柯里化函数有延迟调用的作用

2.3、手写万能柯里化函数
我们可以这么理解:所谓的柯里化函数,就是封装「一系列的处理步骤」,通过闭包将参数集中起来计算,最后再把需要处理的参数传进去。那如何实现 currying 函数呢?

实现原理就是「用闭包把传入参数保存起来,当传入参数的数量足够执行函数时,就开始执行函数」。上面延迟计算部分已经实现了一个简化版的 currying 函数。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容

  • JS_函数柯里化 与函数绑定密切相关的主体是函数柯里化(function currying),它用于创建已经设置好...
    learninginto阅读 551评论 1 7
  • 柯里化: 一个函数原本有多个参数, 之传入一个参数, 生成一个新函数, 由新函数接收剩下的参数来运行得到结构. 为...
    攻城熊阅读 795评论 2 0
  • 第一次看到柯里化这个词的时候,还是在看一篇算法相关的博客提到把函数柯里化,那时一看这个词就感觉很高端,实际上当你了...
    flowsands阅读 232,437评论 40 282
  • 函数柯里化:提高函数的适用性,同时降低函数的通用性;其实现方式就是固定一些可以预期的参数,然后返回一个特定的函数 ...
    大雄的学习人生阅读 1,965评论 0 0
  • 首先看看柯里化到底是什么? 维基百科上说道:柯里化,英语:Currying(果然是满满的英译中的既视感),是把接受...
    指尖跳动阅读 275评论 0 1