浅析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 圆角div的实现代码
Oct 15 Javascript
下拉菜单点击实现连接跳转功能的js代码
May 19 Javascript
浅谈JavaScript之事件绑定
Jul 08 Javascript
网站接入QQ登录的两种方法
Jul 22 Javascript
js实现(全选)多选按钮的方法【附实例】
Mar 30 Javascript
Bootstrap基本样式学习笔记之表单(3)
Dec 07 Javascript
EditPlus中的正则表达式 实战(2)
Dec 15 Javascript
React Native中Navigator的使用方法示例
Oct 13 Javascript
详解vue2.0模拟后台json数据
May 16 Javascript
图解javascript作用域链
May 27 Javascript
微信小程序入口场景的问题集合与相关解决方法
Jun 26 Javascript
通过实例解析javascript Date对象属性及方法
Nov 04 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
discuz程序的PHP加密函数原理分析
2011/08/05 PHP
PHP下利用shell后台运行PHP脚本,并获取该脚本的Process ID的代码
2011/09/19 PHP
php中二维数组排序问题方法详解
2015/08/28 PHP
PHP如何开启Opcache功能提升程序处理效率
2020/04/27 PHP
jQuery Flash/MP3/Video多媒体插件
2010/01/18 Javascript
js限制文本框只能输入数字方法小结
2014/06/16 Javascript
jQuery实现企业网站横幅焦点图切换功能实例
2015/04/30 Javascript
js+html5实现canvas绘制镂空字体文本的方法
2015/06/05 Javascript
JS 清除字符串数组中,重复元素的实现方法
2016/05/24 Javascript
基于Angularjs实现分页功能
2016/05/30 Javascript
关于jQuery.ajax()的jsonp碰上post详解
2017/07/02 jQuery
vue2.0 循环遍历加载不同图片的方法
2018/03/06 Javascript
vue 每次渲染完页面后div的滚动条保持在最底部的方法
2018/03/17 Javascript
javascript、php关键字搜索函数的使用方法
2018/05/29 Javascript
angular2 NgModel模块的具体使用方法
2019/04/10 Javascript
[48:38]DOTA2亚洲邀请赛 3.31 小组赛 B组 Mineski vs Secret
2018/03/31 DOTA
[08:08]DOTA2-DPC中国联赛2月28日Recap集锦
2021/03/11 DOTA
Python 文件操作技巧(File operation) 实例代码分析
2008/08/11 Python
python计算最大优先级队列实例
2013/12/18 Python
跟老齐学Python之重回函数
2014/10/10 Python
Python使用Mechanize模块编写爬虫的要点解析
2016/03/31 Python
python利用正则表达式搜索单词示例代码
2017/09/24 Python
解决使用pycharm提交代码时冲突之后文件丢失找回的方法
2018/08/05 Python
Python 经典面试题 21 道【不可错过】
2018/09/21 Python
Python找出微信上删除你好友的人脚本写法
2018/11/01 Python
利用Python的sympy包求解一元三次方程示例
2019/11/22 Python
Python标准库itertools的使用方法
2020/01/17 Python
Python限制内存和CPU使用量的方法(Unix系统适用)
2020/08/04 Python
LN-CC中国:高端男装和女装的奢侈时尚目的地
2019/09/14 全球购物
甜美蛋糕店创业计划书
2014/01/30 职场文书
《望洞庭》教学反思
2014/02/16 职场文书
团支书竞选演讲稿
2014/04/28 职场文书
2015年乡镇卫生院妇幼保健工作总结
2015/05/19 职场文书
从np.random.normal()到正态分布的拟合操作
2021/06/02 Python
CSS3 Tab动画实例之背景切换动态效果
2021/08/23 HTML / CSS
Go web入门Go pongo2模板引擎
2022/05/20 Golang