浅析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 相关文章推荐
基于Jquery制作的幻灯片图集效果打包下载
Feb 12 Javascript
jQuery版Tab标签切换
Mar 16 Javascript
document.all的一个比较完整的总结及案例
Jan 31 Javascript
onbeforeunload与onunload事件异同点总结
Jun 24 Javascript
用原生js统计文本行数的简单示例
Aug 19 Javascript
Bootstrap CSS布局之表格
Dec 17 Javascript
jQuery插件FusionCharts绘制的2D帕累托图效果示例【附demo源码】
Mar 28 jQuery
jQuery实现checkbox的简单操作
Nov 18 jQuery
实例详解Node.js 函数
Jun 10 Javascript
JS前端知识点 运算符优先级,URL编码与解码,String,Math,arguments操作整理总结
Jun 27 Javascript
JavaScript工具库MyTools详解
Jan 01 Javascript
在antd4.0中Form使用initialValue操作
Nov 02 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/01 无线电
php的字符串用法小结
2010/06/08 PHP
PHP FOR MYSQL 代码生成助手(根据Mysql里的字段自动生成类文件的)
2011/07/23 PHP
php中防止伪造跨站请求的小招式
2011/09/02 PHP
深入解析PHP 5.3.x 的strtotime() 时区设定 警告信息修复
2013/08/05 PHP
php数组转换js数组操作及json_encode的用法详解
2013/10/26 PHP
分享十款最出色的PHP安全开发库中文详细介绍
2015/03/22 PHP
php截取指定2个字符之间字符串的方法
2015/04/15 PHP
PHP实现的简单组词算法示例
2018/04/10 PHP
JavaScript 在线压缩和格式化收藏
2009/01/16 Javascript
jquery nth-child()选择器的简单应用
2010/07/10 Javascript
JavaScript中对象属性的添加和删除示例
2014/05/12 Javascript
jquery中 $.expr使用实例介绍
2014/06/09 Javascript
js限制文本框的输入内容代码分享(3类)
2015/08/20 Javascript
JS实现的简洁纵向滑动菜单(滑动门)效果
2015/10/19 Javascript
原生js实现图片放大缩小计时器效果
2017/01/20 Javascript
D3.js进阶系列之CSV表格文件的读取详解
2017/06/06 Javascript
解决AjaxFileupload 上传时会出现连接重置的问题
2017/07/07 Javascript
Vue中的Vux配置指南
2017/12/08 Javascript
js canvas实现橡皮擦效果
2018/12/20 Javascript
vuex的数据渲染与修改浅析
2020/11/26 Vue.js
python numpy 按行归一化的实例
2019/01/21 Python
Python基础教程之if判断,while循环,循环嵌套
2019/04/25 Python
Python秒算24点实现及原理详解
2019/07/29 Python
Python字典底层实现原理详解
2019/12/18 Python
利用python画出AUC曲线的实例
2020/02/28 Python
在Mac中PyCharm配置python Anaconda环境过程图解
2020/03/11 Python
python利用线程实现多任务
2020/09/18 Python
CSS3 实现弹跳的小球动画
2020/10/26 HTML / CSS
Shell如何接收变量输入
2012/09/24 面试题
什么是servlet链?
2014/07/13 面试题
国际政治个人自荐信范文
2013/11/26 职场文书
创业计划书中包含的9个方面
2013/12/26 职场文书
优秀大学生求职自荐信范文
2014/04/19 职场文书
教师党员自我剖析材料
2014/09/29 职场文书
HTML5之高度塌陷问题的解决
2022/06/01 HTML / CSS