浅析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 相关文章推荐
说说掌握JavaScript语言的思想前提想学习js的朋友可以看看
Apr 01 Javascript
javascript让setInteval里的函数参数中的this指向特定的对象
Jan 31 Javascript
jquery 的 $("#id").html() 无内容的解决方法
Jun 07 Javascript
js子页面获取父页面数据示例
May 15 Javascript
jquery跟随屏幕滚动效果的实现代码
Apr 13 Javascript
Vue.js学习示例分享
Feb 05 Javascript
基于Vue实现拖拽功能
Jul 29 Javascript
vue组件实现弹出框点击显示隐藏效果
Oct 26 Javascript
微信小程序实现topBar底部选择栏效果
Jul 20 Javascript
如何在JavaScript中优雅的提取循环内数据详解
Mar 04 Javascript
JS动态图片的实现方法完整示例
Jan 13 Javascript
VUE中使用HTTP库Axios方法详解
Feb 05 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数组无限分级数据的层级化处理代码
2012/12/29 PHP
php数组去重实例及分析
2013/11/26 PHP
yii框架表单模型使用及以数组形式提交表单数据示例
2014/04/30 PHP
php绘制一条直线的方法
2015/01/24 PHP
从wamp到xampp的升级之路
2015/04/08 PHP
PHP页面输出搜索后跳转下一页的处理方法
2016/09/30 PHP
用JS控制回车事件的代码
2011/02/20 Javascript
浅析用prototype定义自己的方法
2013/11/14 Javascript
使用js简单实现了tree树菜单
2013/11/20 Javascript
javascript break指定标签打破多层循环示例
2014/01/20 Javascript
页面加载完后自动执行一个方法的js代码
2014/09/06 Javascript
JS实现点击颜色块切换指定区域背景颜色的方法
2015/02/25 Javascript
JS修改iframe页面背景颜色的方法
2015/04/01 Javascript
基于JS实现导航条之调用网页助手小精灵的方法
2016/06/17 Javascript
Node.js + Redis Sorted Set实现任务队列
2016/09/19 Javascript
AngularJS 的$timeout服务示例代码
2017/09/21 Javascript
vuex中使用对象展开运算符的示例
2017/09/25 Javascript
js断点调试心得分享(必看篇)
2017/12/08 Javascript
clipboard.js在移动端复制失败的解决方法
2018/06/13 Javascript
详解webpack打包第三方类库的正确姿势
2018/10/20 Javascript
微信小程序实现底部弹出框
2020/11/18 Javascript
微信小程序实现音乐播放页面布局
2020/12/11 Javascript
[01:32]DOTA2 2015国际邀请赛中国区预选赛第四日战报
2015/05/29 DOTA
[01:07:15]DOTA2-DPC中国联赛 正赛 DLG vs XG BO3 第二场 1月25日
2021/03/11 DOTA
python类的继承实例详解
2017/03/30 Python
python调用摄像头的示例代码
2020/09/28 Python
解决Python 写文件报错TypeError的问题
2020/10/23 Python
python 邮件检测工具mmpi的使用
2021/01/04 Python
用gpu训练好的神经网络,用tensorflow-cpu跑出错的原因及解决方案
2021/03/03 Python
国际领先的在线时尚服装和配饰店:DressLily
2019/03/03 全球购物
远东集团网络工程师面试题
2014/10/20 面试题
JavaScript实现前端网页版倒计时
2021/03/24 Javascript
产品销售员岗位职责
2013/12/18 职场文书
幼儿教师三分钟演讲稿
2019/06/21 职场文书
2019最新企业员工考勤管理制度(通用版)!
2019/07/02 职场文书
Python+Appium自动化测试的实战
2021/06/30 Python