浅析JavaScript 函数柯里化


Posted in Javascript onSeptember 08, 2020

柯里化 (Currying)是把接收多个参数的原函数变换成接受一个单一参数(原来函数的第一个参数的函数)并返回一个新的函数,新的函数能够接受余下的参数,并返回和原函数相同的结果。

ES6的方式实现柯里化的通用

function currying(fn,...rest1){
	return function(...rest2){
		//这里用apply 是为把数组形式的参数直接传入原函数 null是因为不需要改变this
		return fn.apply(null,rest1.concat(rest2));
	}
}

将一个sayHello函数柯里化

function sayHello(name,age,fruit){
	console.log(`我叫${name},我${age}岁了,我喜欢吃${fruit}`);
}

//传入第一个参数
let curryingShowMsg = currying(sayHello,'小明');
//执行传入剩余参数
curryingShowMsg(22,'芒果');

反柯里化 和柯里化刚好相反。为了让方法使用场景更广,使用反柯里化,可以把原生方法借出来,让任何对象拥有原生对象的方法。

二者的区别

//柯里化
//function(arg1,arg2) => function(arg1)(arg2);
//function(arg1,arg2,...,argn) => function(arg1)(arg2)(...)(argn)
//反柯里化
//obj.func(arg1,arg2) => func(obj,arg1,arg2)

ES6实现一个反柯里化

function unCurrying(fn){
	//tar 是我们借给的对象 以前需要xxx.fn(xx) 现在就可以fn(xxx,xx)
	return function(tar,...argu){
		return fn.apply(tar,argu);
	}
}
//比如我们想把Array.prototype.push方法从原生借出来
let push = unCurrying(Array.prototype.push);
//arrguments是我们借给的对象
push(arguments,4);

函数柯里化的高阶实现 ,上面的函数只实现一层简单的柯里化 如果实现完全的柯里化func(xx)(xx)(xx)(xx)的话,我们要反复嵌套我们的柯里化函数,这里我们实现一个更高阶的柯里化通用方法。

function curryingHelper(fn,len){
	//这里先说个基本知识点 fn.length 返回的是这个方法需要传入的参数个数
	//这里第一次运行时通过fn.length 后面递归都是用的传入的len len为剩余的参数个数
	const length = len || fn.length;
	return function(...rest){
		//判断这次传入的参数是否大于等于剩下的参数 如果不是递归返回下一个方法继续传参
		return rest.length >= length 
		? fn.apply(this,rest)
		: curryingHelper(currying.apply(this,[fn].concat(rest)),length-rest.length)
	}
}
//还是刚才的sayHello 函数
let betterShowMsg = curryingHelper(sayHello);
//自动控制传参层数
betterShowMsg('zyx')(22)('葡萄');
betterShowMsg('zyx',22)('葡萄');

柯里化的三种用法

1 参数的复用

function Say(name,some){
	console.log(name + '说' + some);
}
//如果我们只想让zyx说一些东西
let zyxSay = currying(Say,'zyx');
zyxSay('1111');//zyx说1111

2 提高适用性

//通用函数解决了兼容性的问题,但是同时在不同场景下,我们可能同一种规则需要反复使用
//这就可能会造成代码的重复性 比如

function square(i){ return i*i }//平方
function dubble(i){ return i*2 }//双倍
function map(handler,list){
	//handle 是操作的规则 list是操作的arrguments
	return list.map(handler)
}

map(square,[1,2,3]);//数组每一项平方
map(dubble,[1,2,3]);//数组每一项加倍
//这就是通用性 我可以用同一个函数做很多不同的操作
//但是如果我们需要大量做平方操作 每次我们都需要传入方法再传入数组就造成的代码浪费
//这时我们通过柯里化提高实用性

let mapSQ = currying(map,square);//直接定义出来的新的平凡操作函数
mapSQ([1,2,3]);//以后就不用传入操作方法了

3 延迟执行

let add = function(...rest){
	//定义一个闭包保存_args
	const _args = [];
	return function cb(...rest){
		if(rest.length == 0){
			//如果不穿参数了 也就是add() 说明我们需要最后执行函数了
			let res = 0;
			//累加
			console.log(_args);
			for(let data of _args){
				res += data;
			}
			return res;
		}else{
			_args.push(...rest);
			//为了锁住args 闭包
			return _args;
		}
	}
}()

add(1);
add(2);
let a = add();
console.log(a);//3

以上就是浅析JavaScript 函数柯里化的详细内容,更多关于JavaScript 函数柯里化的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
用js闭包的方法实现多点标注冒泡示例
May 29 Javascript
js实现背景图片感应鼠标变化的方法
Feb 28 Javascript
JS实现在线统计一个页面内鼠标点击次数的方法
Feb 28 Javascript
解析Node.js异常处理中domain模块的使用方法
Feb 16 Javascript
微信和qq时间格式模板实例详解
Oct 21 Javascript
jqgrid实现简单的单行编辑功能
Sep 30 Javascript
two.js之实现动画效果示例
Nov 06 Javascript
jQuery实现基本动画效果的方法详解
Sep 06 jQuery
微信小程序首页的分类功能和搜索功能的实现思路及代码详解
Sep 11 Javascript
Vue.js如何使用Socket.IO的示例代码
Sep 05 Javascript
vue el-table实现行内编辑功能
Dec 11 Javascript
Node.js API详解之 os模块用法实例分析
May 06 Javascript
Vue.js使用axios动态获取response里的data数据操作
Sep 08 #Javascript
JavaScript 事件代理需要注意的地方
Sep 08 #Javascript
Vue axios 跨域请求无法带上cookie的解决
Sep 08 #Javascript
详解JavaScript的this指向和绑定
Sep 08 #Javascript
vue点击按钮实现简单页面的切换
Sep 08 #Javascript
Vue filter 过滤器、以及在table中的使用介绍
Sep 07 #Javascript
VUE中setTimeout和setInterval自动销毁案例
Sep 07 #Javascript
You might like
阿拉伯的咖啡与水烟
2021/03/03 咖啡文化
怎样在UNIX系统下安装php3
2006/10/09 PHP
php-cli简介(不会Shell语言一样用Shell)
2013/06/03 PHP
使用URL传输SESSION信息
2015/07/14 PHP
PHP表单数据写入MySQL数据库的代码
2016/05/31 PHP
php基于curl实现的股票信息查询类实例
2016/11/11 PHP
PHP自动补全表单的两种方法
2017/03/06 PHP
JS类的封装及实现代码
2009/12/02 Javascript
用json方式实现在 js 中建立一个map
2014/05/02 Javascript
BootStrap中Datetimepicker和uploadify插件应用实例小结
2016/05/26 Javascript
JQueryEasyUI之DataGrid数据显示
2016/11/23 Javascript
利用jQuery.Validate异步验证用户名是否存在(推荐)
2016/12/09 Javascript
jQuery插件FusionCharts实现的3D柱状图效果实例【附demo源码下载】
2017/03/03 Javascript
微信小程序实现上传图片裁剪图片过程解析
2019/08/22 Javascript
node koa2 ssr项目搭建的方法步骤
2020/12/11 Javascript
[02:24]DOTA2亚洲邀请赛 NAVI战队出场宣传片
2015/02/07 DOTA
[01:01:52]完美世界DOTA2联赛PWL S2 GXR vs Magma 第二场 11.25
2020/11/26 DOTA
python处理json数据中的中文
2014/03/06 Python
用Python制作检测Linux运行信息的工具的教程
2015/04/01 Python
Python基于pygame实现的弹力球效果(附源码)
2015/11/11 Python
Python中格式化format()方法详解
2017/04/01 Python
Python设计模式之中介模式简单示例
2018/01/09 Python
Python Scapy随心所欲研究TCP协议栈
2018/11/20 Python
python3.7简单的爬虫实例详解
2019/07/08 Python
Python实现自动整理文件的脚本
2020/12/17 Python
详解前端HTML5几种存储方式的总结
2016/12/27 HTML / CSS
SportsDirect.com马来西亚:英国第一体育零售商
2018/11/21 全球购物
Ibatis如何调用存储过程
2015/05/15 面试题
预备党员入党自我评价范文
2014/03/10 职场文书
租赁协议书范本
2014/04/22 职场文书
挂靠协议书范本
2014/04/22 职场文书
公安机关纪律作风整顿个人剖析材料材料
2014/10/10 职场文书
西湖英语导游词
2015/02/06 职场文书
使用css样式设计一个简单的html登陆界面的实现
2021/03/30 HTML / CSS
win10安装配置nginx的过程
2021/03/31 Servers
Docker部署Mysql8的实现步骤
2022/07/07 Servers