浅析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对象 继承
Jun 19 Javascript
javascript作用域容易记错的两个地方分析
Jun 22 Javascript
jquery插件实现鼠标经过图片右侧显示大图的效果(类似淘宝)
Feb 04 Javascript
jQuery中on()方法用法实例
Jan 19 Javascript
jQuery性能优化技巧分析
Feb 20 Javascript
JavaScript 表单处理实现代码
Apr 13 Javascript
BootStrap使用popover插件实现鼠标经过显示并保持显示框
Jun 23 Javascript
原生js实现放大镜效果
Jan 11 Javascript
angular 动态组件类型详解(四种组件类型)
Feb 22 Javascript
jQuery异步提交表单实例
May 30 jQuery
Express本地测试HTTPS的示例代码
Jun 06 Javascript
微信小程序实现分享到朋友圈功能
Jul 19 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
jQuery 源码分析笔记
2011/05/25 PHP
Yii2 GridView实现列表页直接修改数据的方法
2016/05/16 PHP
laravel框架中表单请求类型和CSRF防护实例分析
2019/11/23 PHP
js实现简单模态窗口,背景灰显
2008/11/14 Javascript
Domino中运用jQuery读取视图内容的方法
2009/10/21 Javascript
CSS+Jquery实现页面圆角框方法大全
2009/12/24 Javascript
js实现字符串转日期格式的方法
2015/05/20 Javascript
深入浅析NodeJs并发异步的回调处理
2015/12/21 NodeJs
基于BootStrap Metronic开发框架经验小结【二】列表分页处理和插件JSTree的使用
2016/05/12 Javascript
js验证框架之RealyEasy验证详解
2016/06/08 Javascript
分享JS数组求和与求最大值的方法
2016/08/11 Javascript
利用VUE框架,实现列表分页功能示例代码
2017/01/12 Javascript
深入理解Vue官方文档梳理之全局API
2017/11/22 Javascript
Vue js 的生命周期(看了就懂)(推荐)
2019/03/29 Javascript
小程序跨页面交互的作用与方法详解
2020/01/07 Javascript
element-ui table行点击获取行索引(index)并利用索引更换行顺序
2020/02/27 Javascript
vue中的使用token的方法示例
2020/03/10 Javascript
js 闭包深入理解与实例分析
2020/03/19 Javascript
javascript开发实现贪吃蛇游戏
2020/07/31 Javascript
Python模块学习 re 正则表达式
2011/05/19 Python
使用python Django做网页
2013/11/04 Python
Python中使用插入排序算法的简单分析与代码示例
2016/05/04 Python
Python Numpy 数组的初始化和基本操作
2018/03/13 Python
修复 Django migration 时遇到的问题解决
2018/06/14 Python
python根据list重命名文件夹里的所有文件实例
2018/10/25 Python
10 分钟快速入门 Python3的教程
2019/01/29 Python
python操作openpyxl导出Excel 设置单元格格式及合并处理代码实例
2019/08/27 Python
flask框架自定义过滤器示例【markdown文件读取和展示功能】
2019/11/08 Python
嘻哈珠宝品牌:KRKC&CO
2020/10/19 全球购物
eDreams德国:南欧领先的在线旅游公司
2020/12/07 全球购物
网站编辑求职信
2013/10/17 职场文书
环保专业大学生职业规划设计
2014/01/10 职场文书
公司门卫岗位职责范本
2014/07/08 职场文书
工作汇报开头与结尾怎么写
2014/11/08 职场文书
送给客户微信问候语!
2019/07/04 职场文书
详细了解MVC+proxy
2021/07/09 Java/Android