之前的系列,我们介绍了什么是高阶函数。所有以函数作为参数的函数,都可以叫作高阶函数。并且我们常常利用高阶函数来封装一些公共逻辑。

本次,我们要继续学习,继续记录,柯里化。柯里化,其实就是高阶函数的一种特殊用法。

柯里化是指这样一个函数(假设叫做createCurry),它接收函数A作为参数,运行后能够返回一个新的函数,并且这个新的函数能够处理函数A的剩余参数。

文字总是不那么好去理解,下面我们就通过例子来理解吧。

假设有一个接收三个参数的函数A。

function A(a, b, c) {// to do something
}复制代码

又假设我们有一个已经封装好了的柯里化通用函数createCurry。他接收bar作为参数,能够将A转化为柯里化函数,返回结果就是这个被转化之后的函数。

var _A = createCurry(A);复制代码

那么_A作为createCurry运行的返回函数,能够处理A的剩余参数。因此下面的运行结果都是等价的。

_A(1, 2, 3);
_A(1,2)(3);
_A(1)(2,3);
_A(1)(2)(3);
A(1,2,3);复制代码

函数A被createCurry转化之后得到柯里化函数_A,_A能够处理A的所有剩余参数。因此柯里化也被称为部分求值。

在简单的场景下,我们可以不借助柯里化通用式来转化得到柯里化函数,仅凭借眼力自己封装。

例如,有一个简单的加法函数,它能够将自身的三个参数加起来并返回计算结果。

function add(a, b, c) {return a + b + c;
}复制代码

那么add函数的柯里化函数_add则可以写成:

function _add(a) {return function(b) {return function(c) {return a + b + c;}}
}复制代码

因此下面的运算方式是等价的。

add(1, 2, 3);
_add(1)(2)(3);复制代码

当然,柯里化通用式具备更加强大的能力,仅靠眼力劲可不行。因此我们更需要知道如何封装这样一个柯里化的通用式。

首先通过_add可以看出,柯里化函数的运行过程其实是一个参数收集过程,我们将每一次传入的参数收集起来,并在最里层进行处理。因此在实现createCurry时,可以借助这个思路来进行封装。

代码如下:

// arity 用来标记剩余参数的个数
// args 用来收集参数function createCurry(func, arity, args) {//第一次执行时,并不会传入arity,而是直接获取func参数的个数 func.lengthvar arity = arity || func.length;//第一次执行也不会传入args,而是默认为空数组var args = args || [];var wrapper = function() {//将wrapper中的参数收集到args中var _args = [].slice.call(arguments);[].push.apply(args, _args);//如果参数个数小于最初的func.length,则递归调用,继续收集参数if(_args.length < arity) {arity -= _args.length;return createCurry(func, arity, args);}//参数收集完毕,执行funcreturn func.apply(func, args);}return wrapper;
}复制代码

是不是有些不太容易理解,所以要多阅读几次。这个createCurry的封装其实是借助了闭包和递归,实现一个参数收集,并在收集完毕之后执行所有参数。

不知道您是否有发现,函数经过createCurry转化为一个柯里化函数后,最后执行的结果,不是正相当于执行函数自己吗?柯里化是不是把简单的问题复杂化了?

没错,柯里化确实是把简单的问题复杂化了,但在复杂化的同时,我们在使用函数时拥有了更多的自由度。对于函数参数的自由处理,正是柯里化的核心所在。

下面举一个常见的例子。

如果想要验证一串数字是否是正确的手机号,那么按照正常思路来做,可能就会写出代码如下唉:

fuction checkPhone(phoneNumber) {return /^1[34578]\d{9}$/.test(phoneNumber);
}复制代码

而如果想要验证是否是邮箱呢?你然后在写一个,可是我们还会遇到更多需要验证的消息,如“身份证、登录名、密码...”。为了偷懒,我们应该封装一个更为通用的函数,把待验证的正则表达式与将要被验证的字符串作为参数传入:

function check(reg, targetString) {return reg.test(targetSting);
}复制代码

但是这样封装之后,在使用时又会遇到问题,因为总是需要输入一串正则,一串字符,这样就导致使用时效率低下。

这个时候,我们就可以借助柯里化,在check的基础上再做一层封装,以简化使用。

var _check = createCurry(check);var checkPhone = _check(/xxxxxx/);
var checkEmail = _check(/xxxxxx/);复制代码

最后在使用时就会变得更加简洁与直观了。

checkPhone('13979227922');
checkEmail('xsxsx@163.com');复制代码

在这个过程中可以发现,柯里化能够应对更加复杂的逻辑封装。当情况变得多变时,柯里化依然能够应付自如。

虽然柯里化在一定程度上将问题复杂化,也让代码变得更加不容易理解,但是柯里化在面对复杂情况时的灵活性却让我们不得不爱。

深入理解javascript系列(十七):函数柯里化相关推荐

  1. JavaScript 专题之函数柯里化

    JavaScript 专题系列第十三篇,讲解函数柯里化以及如何实现一个 curry 函数 定义 维基百科中对柯里化 (Currying) 的定义为: In mathematics and comput ...

  2. 深入详解python高级特性——函数柯里化(Currying)与反柯里化

    前言:本章的内容本来很简单,但是涉及到的理论部分相对较多,想要彻底弄懂前因后果需要具备以下几个知识点, (1)python的高阶函数 (2)python的装饰器本质 (3)Python的functoo ...

  3. 打造属于自己的underscore系列(五)- 偏函数和函数柯里化

    这一节的内容,主要针对javascript函数式编程的两个重要概念,偏函数(partial application) 和函数柯里化(curry)进行介绍.着重讲解underscore中对于偏函数应用的 ...

  4. 带你看懂javascript函数柯里化(currying)

    1.什么是柯里化 这里参照百度百科: 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技 ...

  5. JavaScript 中函数 柯里化风格的运用

    导语 当我第一次看见 柯里化 这个词语的时候,我也表现出一脸懵,在代码程序中,看见这种 "高大上"的一些词汇叫法的时候,下意识的会觉得这个概念很难很深奥,但是当冷静下来,去深究过后 ...

  6. JavaScript函数柯里化详解

    目录 一.简单了解apply和call 二.什么是函数柯里化? 三.写一个公共的柯里化函数 四.创建一个灵活的柯里化函数 五.写一个可控制的执行时间的柯里化函数 一.简单了解apply和call ca ...

  7. 【JavaScript】函数柯里化

    文章目录 1. 什么是函数柯里化 2. 柯里化常用场景 2.1 参数复用 2.2 提前返回 2.3 延迟执行 3. 经典例题 3.1 封装通用柯里化函数 3.2 创建一个灵活的多步执行的柯里化函数 3 ...

  8. JavaScript函数柯里化

    一.简单了解apply和call call 和 apply 都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向. call 和 appl ...

  9. 了解js基础知识中的作用域和闭包以及闭包的一些应用场景,浅析函数柯里化

    js基础知识中的作用域和闭包 一.作用域 1.作用域.自由变量简介 (1)作用域定义 (2)作用域实例演示 (3)自由变量定义 (4)自由变量实例演示 2.作用域链简介 (1)作用域链定义 (2)作用 ...

最新文章

  1. 笔记本独显无输出_高价位笔记本电脑推荐(一万一以上)
  2. SAP RETAIL 根据Allocation Rule去创建分配表
  3. 使用 plsql 时的配置信息(连远程数据库服务器 到 在本机安装 oracle )
  4. webpack+vue动态加载组件尝试
  5. python怎么理解函数的参数_Python中函数参数理解
  6. 485串口测试工具软件_【实例】如何用串口软件调试变频器?
  7. 图见-未来 | 创邻科技 Galaxybase免费版发布会回顾
  8. 风变编程,帮助你从零开始学习编程
  9. 【论文阅读】Tightly Coupled 3D Lidar Inertial Odometry and Mapping
  10. java 汽车类_汽车类 - java代码库 - 云代码
  11. 皇图中原青豫大战打到服务器维护,【九州皇图】青、豫国砸再现激情
  12. 20种简单美化照片PS技术
  13. 《A Traceable and Revocable Ciphertext-Policy Attribute-based Encryption Scheme Based》属性加密机制
  14. 高等数学:第一章 函数与极限(2)数列极限
  15. 2021十大手表品牌TOP排行榜
  16. 开源电子表格Luckysheet强势推出在线协作
  17. python基础:廖雪峰的官方网站Python(部分)笔记
  18. 魏副业而战:闲鱼无货源爆款热销产品推荐
  19. 2018ccpc吉林 C:JUSTICE 思维
  20. strace简单介绍

热门文章

  1. Ceph分布式存储学习指南1.10 iRODS
  2. GreenPlum的并行查询优化策略
  3. 用计算机自我介绍,计算机个人简历:计算机专业简历自我介绍【四篇】供参考使用(5页)-原创力文档...
  4. oracle隐藏游标,Oracle 存储过程隐藏游标
  5. android 串口调试adb,Android系统 debug 技巧(最全最强adb 串口调试命令)
  6. java heap space flex_Flash builder 4内存优化之java heap space解决办法
  7. Zookeeper基于Java访问-节点事件监听
  8. checkInterruptWhileWaiting
  9. 初探Spring MVC 请求处理流程
  10. ApplicationContext应用上下文获取方式