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

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

在函数式编程中,函数柯里化是指将接受多个参数的函数转为接受单个参数的函数。

背景基础知识

1)函数的length属性--返回定义时的函数参数个数

// 应用:可以用来判断函数定义时和调用时的参数差异function test(a,b,v) {  // ...}test(1,2,3,4,5)console.log(test.length === 3) // true// 实际参数长度5,定义时参数长度为3

2) 函数的arguments对象:函数调用时传入的参数,与函数声明的参数无关

function a() {    console.log(Array.prototype.slice.call(arguments, 1)) // [2,3,4]}a(1,2,3,4);
  •    获取函数的所有参数;
  •    类数组的对象({0: value, 1: value, 2: value, ..., length: N}),有需要时可以通过slice方法转为数组
  •    非严格模式可以修改arguments的值,严格模式无效
  •    非严格模式下,callee属性可以返回函数本身,用于自身调用;严格模式无效
  •    length属性,表示实际调用参数的个数;与定义时的参数个数无关。
    function fn(a, b) {  console.log(arguments.length);  // 3  console.log(arguments.callee === fn) // true  // 转为数组  console.log(Array.prototype.slice.call(arguments)); // [1,2,3]  arguments[0] = 5;  arguments[1] = 6;  return a + b;}fn(1,2,3); // 11

3) valueOf() 和toString() 方法

由下面的运行结果可以指导,返回函数赋值的变量时,会默认调用函数的toString()方法;

⚠️:下面的运行结果都是在chrome浏览器的控制台的运行结果;firefox浏览器结果不同

⚠️上图的程序中最后只调用了add函数,所以直接返回fn,不会进入调用fn;

应用:

柯里化的实现涉及到了闭包,递归,arguments的存取

 1.题目要求:(当目标函数参数个数固定的时候, 将已知函数转换成柯里化函数)

function add(a,b,c) {     return a+b+c;  }  // 目标:将add改为通用的柯里化函数,使得下面运算结果和add相同  // 并不是要重新写一个函数,只是修改传参形式,最后还是调用的原来的函数
_add(a)(b)(c);   _add(a)(b,c);    _add(a,b)(c); //---> return a+b+c    /* ->createCurry(add)(a,b)(c)-> createCurry(add, a,b)(c)\ ->createCurry(add,a,b,c) -> add(a,b,c);    从上面可以看到,createCurry是一个收集参数的过程;直到收集到函数定义时的参数个数 */

柯里化函数:

// 通用的柯里化创建函数如下  function createCurry(fn, args) { // args用于表示已经收集到的参数    const arity = fn.length; // 定义时函数fn的参数个数    const collectedArgs = args || []; // 第一次为undefined    return function() {         const _args = Array.prototype.slice.call(arguments);        const allargs = _args.concat(collectedArgs); // 到此为止收集到的所有的参数        const argsLength = allargs.length;        if (argsLength < arity) {             // 收集的参数个数还

2. 通用柯里化函数(以上面的题目为例,如果参数不固定);

function add() {   var args = Array.prototype.slice.call(arguments); // 存储收集的参数    var fn = function() { // 函数定义,不调用就不会执行;        var newArgs = args.concat(Array.prototype.slice.call(arguments));        return add.apply(this, newArgs); // 回调停止条件是根据调用情况,不调用就停止    }    fn.toString = function() {        return args.reduce(function(a, b) {            return a + b;        })    }    return fn;}console.log(add(1)(2)(3)(4)) // f 10 function类型console.log(add(1)(2)) // f 3 function类型Number(add(1)(2))  --- 3

 

优缺点:

1.优点:

 1)可以实现参数复用;

 2)实现延迟执行;先收集所有参数,最后执行;

 3)固定易变参数

Function.prototype.bind = function() {    const args = Array.prototype.slice.call(arguments);    const context = args.shift(); // 第一个参数是绑定的对象;    const _this = this;    return function() {        const allArgs = args.concat(Array.prototype.slice.call(arguments));        return _this.apply(context, allArgs);    }}function fn() {    return this.a;}const obj = { a : 3 };var newFn = fn.bind(obj)(3);console.log(newFn); // 3

缺点: 

1. 闭包占用大量内存,产生性能问题

2.argument存取效率低

3. 递归效率低

  

转载于:https://www.cnblogs.com/lyraLee/p/11445191.html

你可能感兴趣的文章
Gcc 安装过程中部分配置
查看>>
Logparser介绍
查看>>
Js实现客户端表单的验证
查看>>
python使用input()来接受字符串时一直报错“xxx is not defined”
查看>>
加解密与数据校验
查看>>
stm8s_IAP_xmode串口升级
查看>>
usb 编程知识 总结
查看>>
2016.7.15 落实字符及字符串读取的结果
查看>>
他看了几千份技术简历,愿意把技术简历的秘籍传授给你
查看>>
Struts2学习(三)
查看>>
学习Linux的第十二课时
查看>>
使用电子邮件模板
查看>>
IoC 依赖注入、以及在Spring中的实现
查看>>
机器学习 —— 概率图模型(贝叶斯网络)
查看>>
树、森林和二叉树的转换
查看>>
Array:Missing Number
查看>>
数列有序!
查看>>
jQuery1.11源码分析(2)-----Sizzle源码中的正则表达式[原创]
查看>>
javascript面向对象学习(一)
查看>>
高可用redis 缓存搭建
查看>>