一个关于柯里化函数的实现解析

作者 : 开心源码 本文共2174个字,预计阅读时间需要6分钟 发布时间: 2022-05-12 共78人阅读

本篇内容主要参考了以下文章:
从 sum(2)(3) == sum(2, 3) 到实现柯里化函数
JavaScript专题之函数柯里化

柯里化定义

在数学和计算机科学中,柯里化是一种将用多个参数的一个函数转换成一系列用一个参数的函数的技术。

一个柯里化函数的实现

在上面两篇文章中,两位作者都比较详细的分析了柯里化函数的实现方式,特别是冴羽的文章中给出了详细的从零开始实现柯里化函数的方法,在这里我就不再赘述了。

在这里我主要针对上面第一个文章中的实现方法,进行一下执行过程的分析。主要是针对其中的具体的少量执行过程单独看代码还是不甚明了,特此详细执行分析一下以作了解,加深记忆。

实现方式

这个方式是我感觉最容易接受的

function curry(fn, argLen, currArgs) {    return function() {        console.log("arguments:", arguments, arguments.length)        var args = [].slice.call(arguments);        console.log("args:", args)        // 初次调使用时未提供最后一个参数        if (currArgs !== undefined) {            args = args.concat(currArgs);        }        // 递归出口        if (args.length == argLen) {            return fn.apply(this, args);        } else {            return curry(fn, argLen, args);        }    }}function sumOf(a, b, c, d) {    return a + b + c + d;}// 改造普通函数,返回柯里函数var sum = curry(sumOf, 4);

下面我们分别来看一下几种不同的传参方式的执行过程是怎样样的

sum(1,2,3,4)

>sum(1,2,3,4)arguments: Arguments(4) [1, 2, 3, 4, callee: ?, Symbol(Symbol.iterator): ?] 4args: (4) [1, 2, 3, 4]

sum(1,2,3)(4)

>sum(1,2,3)(4)arguments: Arguments(3) [1, 2, 3, callee: ?, Symbol(Symbol.iterator): ?] 3args: (3) [1, 2, 3]arguments: Arguments [4, callee: ?, Symbol(Symbol.iterator): ?] 1args: [4]

sum(1,2)(3,4)

>sum(1,2)(3,4)arguments: Arguments(2) [1, 2, callee: ?, Symbol(Symbol.iterator): ?] 2args: (2) [1, 2]arguments: Arguments(2) [3, 4, callee: ?, Symbol(Symbol.iterator): ?] 2args: (2) [3, 4]

通过上面针对几种传参方式的执行过程的分析,我们可以清楚地看出其中少量关键变量的内容,这样就让我们能够清楚地了解了柯里化函数的执行过程

个人优化

针对上面的执行方式,我们可以看出除了需要被柯里化的函数外,还需要根据这个函数的参数数量传入对应的数量值,这个并不是那么的方便。不妨改进一下

function curry(fn, currArgs) {    return function() {        console.log("arguments:", arguments, arguments.length)        var args = [].slice.call(arguments);        console.log("args:", args)        // 初次调使用时未提供最后一个参数        if (currArgs !== undefined) {            args = args.concat(currArgs);        }        // 递归出口        if (args.length == fn.length) {            return fn.apply(this, args);        } else {            return curry(fn, args);        }    }}

这里我们通过利使用length 属性指明函数的形参个数,来获取被柯里化函数的参数数量,这样就不需要我们在额外传入了。但是此时需要注意的是,被柯里化的函数的参数不能有默认值,不然的话,length属性就没有意义了。所以这个方式也不是完美的。

小结

简单来说,实现柯里化函数的方式基本都会需要根据参数以及递归方式来实现,这样才能让我们通过拆分参数的方式来调使用一个多参数的函数方法。这样的好处是减少重复传递不变的部分参数,将柯里化后的callback参数传递给map, filter等函数

var persons = [{name: 'kevin', age: 11}, {name: 'daisy', age: 24}]let getProp = _.curry(function (key, obj) {    return obj[key]});let names2 = persons.map(getProp('name'))console.log(names2); //['kevin', 'daisy']let ages2 = persons.map(getProp('age'))console.log(ages2); //[11,24]

但是也不得不承认,这是个非常高阶的使用法,普通的开发场景中很少会被用,毕竟了解并不是那么的简单。

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 一个关于柯里化函数的实现解析

发表回复