浅析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 相关文章推荐
javascritp实现input输入框相关限制用法
Jun 29 Javascript
JS按位非(~)运算符与~~运算符的理解分析
Jul 31 Javascript
解析JavaScript中instanceof对于不同的构造器或许都返回true
Dec 03 Javascript
JS给超链接加确认对话框的方法
Feb 24 Javascript
基于jquery编写分页插件
Mar 07 Javascript
微信公众号开发 实现点击返回按钮就返回到聊天界面
Dec 15 Javascript
详解javascript立即执行函数表达式IIFE
Feb 13 Javascript
React学习笔记之列表渲染示例详解
Aug 22 Javascript
最基础的vue.js双向绑定操作
Aug 23 Javascript
Es6 Generator函数详细解析
Feb 24 Javascript
Node.js爬虫如何获取天气和每日问候详解
Aug 26 Javascript
JS实现的雪花飘落特效示例
Dec 03 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 字符截取 解决中文的截取问题,不用mb系列
2009/09/29 PHP
php中使用Curl、socket、file_get_contents三种方法POST提交数据
2011/08/12 PHP
深入解析php中的foreach问题
2013/06/30 PHP
PHP把JPEG图片转换成Progressive JPEG的方法
2014/06/30 PHP
PHP随机获取未被微信屏蔽的域名(微信域名检测)
2017/03/19 PHP
用js解决数字不能换行问题
2010/08/10 Javascript
跟我学Nodejs(三)--- Node.js模块
2014/05/25 NodeJs
IE下通过a实现location.href 获取referer的值
2014/09/04 Javascript
JavaScript设计模式之代理模式介绍
2014/12/28 Javascript
Javascript基础教程之switch语句
2015/01/18 Javascript
JavaScript让Textarea支持tab按键的方法
2015/06/26 Javascript
jQuery动画效果相关方法实例分析
2015/12/31 Javascript
进阶之初探nodeJS
2017/01/24 NodeJs
vue获取dom元素注意事项
2017/12/28 Javascript
jQuery实现的五星点评功能【案例】
2019/02/18 jQuery
vue自动路由-单页面项目(非build时构建)
2019/04/30 Javascript
Vue用mixin合并重复代码的实现
2020/11/27 Vue.js
Python标准异常和异常处理详解
2015/02/02 Python
Python实现多线程HTTP下载器示例
2017/02/11 Python
Python排序搜索基本算法之归并排序实例分析
2017/12/08 Python
python实现字符串加密 生成唯一固定长度字符串
2019/03/22 Python
用Python从0开始实现一个中文拼音输入法的思路详解
2019/07/20 Python
基于python实现对文件进行切分行
2020/04/26 Python
如何使用Python处理HDF格式数据及可视化问题
2020/06/24 Python
Python是怎样处理json模块的
2020/07/16 Python
Django 权限管理(permissions)与用户组(group)详解
2020/11/30 Python
DJI大疆德国官方商城:大疆无人机
2018/09/01 全球购物
日本动漫周边服饰销售网站:Atsuko
2019/12/16 全球购物
医学生自我鉴定范文
2013/11/08 职场文书
业务员岗位职责
2013/11/16 职场文书
尽职尽责村干部自我鉴定
2014/01/23 职场文书
党校个人自我鉴定范文
2014/03/28 职场文书
环境日宣传活动总结
2014/07/09 职场文书
干部职工纪律作风整改措施思想汇报
2014/10/11 职场文书
民事起诉书范本
2015/05/19 职场文书
2019送给家人们的中秋节祝福语
2019/08/15 职场文书