浅析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 相关文章推荐
JQuery 简便实现页面元素数据验证功能
Mar 24 Javascript
js优化针对IE6.0起作用(详细整理)
Dec 25 Javascript
jQuery 关于伪类选择符的使用说明
Apr 24 Javascript
使用jQuery重置(reset)表单的方法
May 05 Javascript
js实现键盘控制DIV移动的方法
Jan 10 Javascript
JS实现往下不断流动网页背景的方法
Feb 27 Javascript
微信小程序 解决请求服务器手机预览请求不到数据的方法
Jan 04 Javascript
Bootstrap 模态对话框只加载一次 remote 数据的完美解决办法
Jul 09 Javascript
vue 1.0 结合animate.css定义动画效果
Jul 11 Javascript
通过函数作用域和块级作用域看javascript的作用域链
Aug 05 Javascript
vue中组件的过渡动画及实现代码
Nov 21 Javascript
详解vue中$nextTick和$forceUpdate的用法
Dec 11 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+js实现百度地图多点标注的方法
2016/11/30 PHP
PHP替换Word中变量并导出PDF图片的实现方法
2020/11/26 PHP
javascript引用对象的方法
2007/01/11 Javascript
Jquery实战_读书笔记2 选择器
2010/01/22 Javascript
Javascript倒计时代码
2010/08/12 Javascript
JS操作Cookies包括(读取添加与删除)
2012/12/26 Javascript
jquery实现带二级菜单的导航示例
2014/04/28 Javascript
javascript实现回车键提交表单方法总结
2015/01/10 Javascript
js判断当前页面用什么浏览器打开的方法
2016/01/06 Javascript
js简单时间比较的方法
2016/08/02 Javascript
jQuery按需加载轮播图(web前端性能优化)
2017/02/17 Javascript
JS+DIV实现的卷帘效果示例
2017/03/22 Javascript
Vue.js实现按钮的动态绑定效果及实现代码
2017/08/21 Javascript
原生js实现省市区三级联动代码分享
2018/02/12 Javascript
nodejs实现连接mongodb数据库的方法示例
2018/03/15 NodeJs
js实现拖动缓动效果
2020/01/13 Javascript
Node登录权限验证token验证实现的方法示例
2020/05/25 Javascript
微信小程序实现购物车小功能
2020/12/30 Javascript
跟老齐学Python之不要红头文件(1)
2014/09/28 Python
Python RuntimeError: thread.__init__() not called解决方法
2015/04/28 Python
详解python中executemany和序列的使用方法
2017/08/12 Python
Python读取本地文件并解析网页元素的方法
2018/05/21 Python
python基础梳理(一)(推荐)
2019/04/06 Python
Django中ajax发送post请求 报403错误CSRF验证失败解决方案
2019/08/13 Python
Python上下文管理器全实例详解
2019/11/12 Python
深入CSS3 动画效果的总结详解
2013/05/09 HTML / CSS
一篇文章带你学习CSS3图片边框
2020/11/04 HTML / CSS
施华洛世奇美国官网:SWAROVSKI美国
2018/02/08 全球购物
英国最受欢迎的价格比较网站之一:MoneySuperMarket
2018/12/19 全球购物
护士演讲稿优秀范文
2014/04/30 职场文书
公诉意见书范文
2015/06/05 职场文书
放假通知怎么写
2015/08/18 职场文书
电工实训心得体会
2016/01/14 职场文书
创业计划书之家教托管
2019/09/25 职场文书
创业计划书之儿童理发店
2019/09/27 职场文书
mysql 如何获取两个集合的交集/差集/并集
2021/06/08 MySQL