浅析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 解析xml文件
Aug 09 Javascript
淘宝搜索框效果实现分析
Mar 05 Javascript
合并table相同单元格的jquery插件分享(很精简)
Jun 20 Javascript
详细解读JavaScript编程中的Promise使用
Jul 27 Javascript
深入理解Angular2 模板语法
Aug 07 Javascript
vue-ajax小封装实例
Sep 18 Javascript
利用js编写网页进度条效果
Oct 08 Javascript
基于ES6作用域和解构赋值详解
Nov 03 Javascript
IntelliJ IDEA 安装vue开发插件的方法
Nov 21 Javascript
Vue在页面数据渲染完成之后的调用方法
Sep 11 Javascript
javascript异常处理实现原理详解
Feb 17 Javascript
vue实现打地鼠小游戏
Aug 21 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
PHP里的中文变量说明
2011/07/23 PHP
PHP中让curl支持sock5的代码实例
2015/01/21 PHP
php使用socket post数据到其它web服务器的方法
2015/06/02 PHP
PHP观察者模式示例【Laravel框架中有用到】
2018/06/15 PHP
选择TreeView控件的树状数据节点的JS方法(jquery)
2010/02/06 Javascript
javascript的函数、创建对象、封装、属性和方法、继承
2011/03/10 Javascript
jQuery制作仿腾讯web qq用户体验桌面
2013/08/20 Javascript
JavaScript中的无阻塞加载性能优化方案
2014/10/10 Javascript
js与css实现弹出层覆盖整个页面的方法
2014/12/13 Javascript
轻松创建nodejs服务器(1):一个简单nodejs服务器例子
2014/12/18 NodeJs
jquery点击缩略图切换视频播放特效代码分享
2015/09/15 Javascript
js获取表格的行数和列数的方法
2015/10/23 Javascript
浅谈toLowerCase和toLocaleLowerCase的区别
2016/08/15 Javascript
Node.js中常规的文件操作总结
2016/10/13 Javascript
解析预加载显示图片艺术
2016/12/05 Javascript
vue.js的安装方法
2017/05/12 Javascript
swiper移动端轮播插件(触碰图片之后停止轮播)
2017/12/28 Javascript
解决VUE双向绑定失效的问题
2019/10/29 Javascript
ng-alain的sf如何自定义部件的流程
2020/06/12 Javascript
Python程序员开发中常犯的10个错误
2014/07/07 Python
Python编程实战之Oracle数据库操作示例
2017/06/21 Python
用Python删除本地目录下某一时间点之前创建的所有文件的实例
2017/12/14 Python
浅析Windows 嵌入python解释器的过程
2019/07/26 Python
python代码如何实现余弦相似性计算
2020/02/09 Python
德国在线购买葡萄酒网站:Geile Weine
2019/09/24 全球购物
自考毕业自我鉴定范文
2013/10/27 职场文书
医药专业应届毕业生求职信范文
2014/01/01 职场文书
小学体育教学反思
2014/01/31 职场文书
乡镇庆八一活动方案
2014/02/02 职场文书
教师拔河比赛广播稿
2014/10/14 职场文书
付款证明格式范文
2015/06/19 职场文书
公司庆典主持词
2015/07/04 职场文书
教师素质教育心得体会
2016/01/19 职场文书
CSS3点击按钮圆形进度打钩效果的实现代码
2021/03/30 HTML / CSS
pycharm debug 断点调试心得分享
2021/04/16 Python
通过feDisplacementMap和feImage实现水波特效
2022/04/24 HTML / CSS