浅析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脚本代码跑起来。
Jan 09 Javascript
actionscript与javascript的区别
May 25 Javascript
jQuery实现的左右移动焦点图效果
Jan 14 Javascript
JS判断字符串变量是否含有某个字串的实现方法
Jun 03 Javascript
微信小程序教程之本地图片上传(leancloud)实例详解
Nov 16 Javascript
JS/jQuery判断DOM节点是否存在的简单方法
Nov 24 Javascript
JS正则表达式验证密码格式的集中情况总结
Feb 23 Javascript
vue如何将v-for中的表格导出来
May 07 Javascript
vue-cli 默认路由再子路由选中下的选中状态问题及解决代码
Sep 06 Javascript
vue 指令之气泡提示效果的实现代码
Oct 18 Javascript
基于vue2的canvas时钟倒计时组件步骤解析
Nov 05 Javascript
vue-cli3.0 环境变量与模式配置方法
Nov 08 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
详解:――如何将图片储存在数据库里
2006/12/05 PHP
php找出指定范围内回文数且平方根也是回文数的方法
2015/03/23 PHP
四个常见html网页乱码问题及解决办法
2015/09/08 PHP
Zend Framework动作助手FlashMessenger用法详解
2016/03/05 PHP
thinkphp框架实现删除和批量删除
2016/06/29 PHP
手把手编写PHP框架 深入了解MVC运行流程
2016/09/19 PHP
php正则去除网页中所有的html,js,css,注释的实现方法
2016/11/03 PHP
浅谈Laravel中的三种中间件的作用
2019/10/13 PHP
js操作select控件的几种方法
2010/06/02 Javascript
javascript间隔刷新的简单实例
2013/11/14 Javascript
Jquery创建一个层当鼠标移动到层上面不消失效果
2013/12/12 Javascript
jquery中get,post和ajax方法的使用小结
2014/02/04 Javascript
jQuery中的通配符选择器使用总结
2016/05/30 Javascript
Vue-cli 使用json server在本地模拟请求数据的示例代码
2017/11/02 Javascript
node实现基于token的身份验证
2018/04/09 Javascript
JavaScript的Object.defineProperty详解
2018/07/09 Javascript
vue监听input标签的value值方法
2018/08/27 Javascript
Antd中单个DatePicker限定时间输入范围操作
2020/10/29 Javascript
vue实现简易计算器功能
2021/01/20 Vue.js
python中的五种异常处理机制介绍
2014/09/02 Python
Python的requests网络编程包使用教程
2016/07/11 Python
python实现的多线程端口扫描功能示例
2017/01/21 Python
Python中的id()函数指的什么
2017/10/17 Python
Python cookbook(数据结构与算法)从序列中移除重复项且保持元素间顺序不变的方法
2018/03/13 Python
如何使用Python进行OCR识别图片中的文字
2019/04/01 Python
Python使用matplotlib实现交换式图形显示功能示例
2019/09/06 Python
MAC平台基于Python Appium环境搭建过程图解
2020/08/13 Python
美国NBA官方商店:NBA Store
2019/04/12 全球购物
法制报告会主持词
2014/04/02 职场文书
环保建议书300字
2014/05/14 职场文书
村居抓节水倡议书
2014/05/19 职场文书
竞聘演讲稿怎么写
2014/08/28 职场文书
党员个人剖析材料
2014/09/30 职场文书
2014幼儿园小班工作总结
2014/11/10 职场文书
Python爬虫入门案例之爬取二手房源数据
2021/10/16 Python
进阶篇之linux环境下安装MySQL数据库
2022/04/09 MySQL