函数柯里化(黑人问号脸)???Currying(黑人问号脸)???妥妥的中式翻译既视感;下面来一起看看究竟什么是函数柯里化:

    维基百科的解释是:把接收多个参数的函数变换成接收一个单一参数(最初函数的第一个参数)的函数,并返回接受剩余的参数而且返回结果的新函数的技术。其由数学家Haskell Brooks Curry提出,并以curry命名。

    概念往往都是干涩且难懂的,让我们用人话来解释就是:如果我们不确定这个函数有多少个参数,我们可以先给它传入一个参数,然后通过JS闭包(如若不懂JS闭包,请先学习闭包知识点再来学习本篇博文  https://www.cnblogs.com/dengyao-blogs/p/11475575.html )来进行返回一个函数,内部函数接收除开第一个参数外的其余参数进行操作并输出,这个就是函数的柯里化;

    举个小例子:

      场景(需求):

      如果我们需要计算一个程序员每天的加班时间,那么我们的第一反应应该是这样;

      

;
function time(x){
    return overtime+=x;
}

time();  //1
time();  //3
time();  //6

  上面的代码固然没有问题,可是需要每天调用都算加一下当天的时间,那么有没有可以偷懒的办法呢?有的!

  

function time(x){
  return function(y){
        return x+y;
    }
}

var times=time(0);
times(3);

  但是上面代码依然存在问题,在实际开发中很多时候我们的参数是不确定的,上面代码虽然简单的实现了柯里化的基本操作,但是对于参数不确定的情况是处理不了的;

  我们再来把代码改建一下:

  

//  首先定义一个变量接收函数var overtime = (function() {//定义一个数组用来接收参数
  var args = [];
//这里运用闭包,调用外部函数返回一个内部函数
  return function() {  //arguments是浏览器内置对象,专门用来接收参数  //如果参数的长度为0即没有参数的时候
    ) {    //定义变量用来累加
      ;    //循环累加,用i和args的长度进行比较
      , l = args.length; i < l; i++) {    //进行累加操作   等价于time=time+args[i]
        time += args[i];
      }    // 返回累加的结果
      return time;    //如果arguments对象参数长度不为零,即有参数的时候
    }else {    //定义的空数组添加arguments参数作为数组项,第一个参数古args作为改变this指向,第二个参数arguments把剩余参数作为数组形式添加至空数组中
      [].push.apply(args, arguments);
    }
  }
})();

overtime(3.5);    // 第一天
overtime(4.5);    // 第二天
overtime(2.1);    // 第三天
//...

console.log( overtime() );    // 10.1

  代码经过我们的改造已经实现了功能,但是这不是一个函数柯里化的完整实现,那么我们要怎么完整实现呢?

  

//定义方法currying,先传入一个参数var currying=function(fn){  //定义空数组装arguments对象的剩余参数
  var args=[];  //利用闭包返回一个函数处理剩余参数
  return function (){    //如果arguments的参数长度为0,即没有剩余参数
    if(arguments.length===0){    //执行上面方法
      return fn.apply(this,args)
    }
    console.log(arguments)  //如果arguments的参数长度不为0,即还有剩余参数  //在数组的原型对象上添加数组,apply用来更改this的指向为args  //将[].slice.call(arguments)的数组添加到原型数组上
   Array.prototype.push.apply(args,[].slice.call(arguments))
    //args.push([].slice.call(arguments))
    console.log(args)  //这里返回的arguments.callee是返回的闭包函数,callee是arguments对象里面的一个属性,用于返回正被执行的function对象
    return arguments.callee
  }
}  //这里调用currying方法并传入add函数,结果会返回闭包内部函数
  var s=currying(add);  //调用闭包内部函数,当有参数的时候会将参数逐步添加到args数组中,待没有参数传入的时候直接调用  //调用的时候支持链式操作
  s(1)(2)(3)();//也可以一次性传入多个参数

s(1,2,3);
  console.log(s());

  

  JS函数柯里化的优点:

    1.可以延迟计算,即如果调用柯里化函数传入参数是不调用的,会将参数添加到数组中存储,等到没有参数传入的时候进行调用;

    2.参数复用,当在多次调用同一个函数,并且传递的参数绝大多数是相同的,那么该函数可能是一个很好的柯里化候选。

   

简单粗暴详细讲解javascript实现函数柯里化的更多相关文章

  1. 简单粗暴详细讲解javascript实现函数柯里化与反柯里化

    函数柯里化(黑人问号脸)???Currying(黑人问号脸)???妥妥的中式翻译既视感:下面来一起看看究竟什么是函数柯里化: 维基百科的解释是:把接收多个参数的函数变换成接收一个单一参数(最初函数的第 ...

  2. JavaScript之函数柯里化

    什么是柯里化(currying)? 维基百科中的解释是:柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术.意思就是当函 ...

  3. Swift函数柯里化(Currying)简谈

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 下面简单说说Swift语言中的函数柯里化.简单的说就是把接收多 ...

  4. JavaScript中的事件循环机制跟函数柯里化

    一.事件循环机制的理解 test();//按秒输出5个5 function test() { for (var i = 0; i < 5; i++) { setTimeout(() => ...

  5. Javascript函数柯里化(curry)

    函数柯里化currying,是函数式编程非常重要的一个标志.它的实现需要满足以下条件,首先就是函数可以作为参数进行传递,然后就是函数可以作为返回值return出去.我们依靠这个特性编写很多优雅酷炫的代 ...

  6. 深入理解javascript函数进阶系列第二篇——函数柯里化

    前面的话 函数柯里化currying的概念最早由俄国数学家Moses Schönfinkel发明,而后由著名的数理逻辑学家Haskell Curry将其丰富和发展,currying由此得名.本文将详细 ...

  7. JavaScript函数柯里化的一些思考

    1. 高阶函数的坑 在学习柯里化之前,我们首先来看下面一段代码: var f1 = function(x){ return f(x); }; f1(x); 很多同学都能看出来,这些写是非常傻的,因为函 ...

  8. 精读JavaScript模式(六),Memoization模式与函数柯里化的应用

    假期就这么结束了!十天假就有三天在路上,真的难受!想想假期除了看了两场电影貌似也没做什么深刻印象的事情.流浪地球,特效还是很赞,不过对于感情的描写还是逃不掉拖沓和尴尬的通病,对于国产科幻还是抱有支持的 ...

  9. 一道javascript面试题(闭包与函数柯里化)

    要求写一个函数add(),分别实现能如下效果: (1)console.log(add(1)(2)(3)(4)()); (2)console.log(add(1,2)(3,4)()); (3)conso ...

随机推荐

  1. 详解 Diff 算法以及循环要加 key 值问题

    上一篇文章我简述了什么是 Virtual DOM,这一章我会详细讲 Diff 算法以及为什么在 React 和 Vue 中循环都需要 key 值. 什么是 DOM Diff 算法 Web 界面其实就是 ...

  2. 关于FFT分析音频的学习

    本文部分知识从以下文章学习: https://zhuanlan.zhihu.com/p/19763358 傅里叶变换的知识 https://www.cnblogs.com/RabbitHu/p/FFT ...

  3. Java基础之二十 并发

    20.1 并发得多面性 并发编程令人困惑的一个主要原因:使用并发时需要解决的问题有多个,而实现并发的方法也有多种,并且在这两者之间没有明显的映射关系. 20.1.1 更快的执行 速度问题初听起来很简单 ...

  4. MySQL Schema与数据类型优化

    Schema与数据类型优化 选择优化的数据类型 1.更小的通常更好 更小的数据类型通常更快,因为它们占用更少的磁盘,内存和CPU缓存 2.简单就好 简单数据类型的操作通常需要更少的CPU周期.例如:整 ...

  5. 封装 Gson 解析Json到对象是否失败

    在使用Google的 Gson 类库解析 Json 数据时,难免会出现解析失败的情况. 在这种情况下,使用 if(obj == null) 是不可行的,fromJson 方法会自动生成对象的实例,所以 ...

  6. alluxio源码解析-netty部分(2)

    netty简介 Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端.   netty作为alluxio中重要的通讯组件 在常见的客户端上传,下载中,都会有n ...

  7. 关于int的范围以及溢出问题

    最近在练一些算法题目的时候恰巧碰到了几道关于int范围与溢出相关的问题,于是就整理一下. 1.原码.补码 在计算机中数值都是用补码表示和存储的(正数补码与原码一致,负数补码是原码符号位不变,其余位取反 ...

  8. 章节十五、9-自定义Loggers

    一.如何给不同的包设置不同的日志级别? 1.针对不同的包来记录不同级别的日志信息 2.在日志xml配置文件中加入配置信息(红色标注) <?xml version="1.0" ...

  9. 微信小程序项目总结-记账小程序(包括后端)

    一.小程序部分 这是理财系统的前端,江苏海洋大学微信小程序比赛,最后获得了一等奖 GitHub:https://github.com/GeorgeLeoo/finance 1. 项目描述 (1). 此 ...

  10. Mysql优化(出自官方文档) - 第八篇(索引优化系列)

    目录 Mysql优化(出自官方文档) - 第八篇(索引优化系列) Optimization and Indexes 1 Foreign Key Optimization 2 Column Indexe ...