浅析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 相关文章推荐
设置iframe的document.designMode后仅Firefox中其body.innerHTML为br
Feb 27 Javascript
offsetHeight在OnLoad中获取为0的现象
Jul 22 Javascript
Jquery 实现grid绑定模板
Jan 28 Javascript
js两种拼接字符串的简单方法(必看)
Sep 02 Javascript
Vue.js 递归组件实现树形菜单(实例分享)
Dec 21 Javascript
AngularJS Select(选择框)使用详解
Jan 18 Javascript
jQuery实现淡入淡出的模态框
Feb 09 Javascript
javascript实现文件拖拽事件
Mar 29 Javascript
Vue CLI3中使用compass normalize的方法
May 30 Javascript
vue element 生成无线级左侧菜单的实现代码
Aug 21 Javascript
使用原生JS实现火锅点餐小程序(面向对象思想)
Dec 10 Javascript
JS函数本身的作用域实例分析
Mar 16 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代码(星期六,星期日总和)
2009/11/12 PHP
PHP 巧用数组降低程序的时间复杂度
2010/01/01 PHP
PHPWind 发帖回帖Api PHP版打包下载
2010/02/08 PHP
基于php 随机数的深入理解
2013/06/05 PHP
学习php开源项目的源码指南
2014/12/21 PHP
PHP使用星号替代用户名手机和邮箱的实现代码
2018/02/07 PHP
jquery怎样实现ajax联动框(二)
2013/03/08 Javascript
jquery实现点击页面计算点击次数
2015/01/23 Javascript
网页前端登录js按Enter回车键实现登陆的两种方法
2016/05/10 Javascript
深入理解(function(){... })();
2016/08/16 Javascript
JavaScript实现类似淘宝的购物车效果
2017/03/16 Javascript
php 修改密码实现代码
2017/05/24 Javascript
Vue.js数据绑定之data属性
2017/07/07 Javascript
图文详解vue框架安装步骤
2019/02/12 Javascript
vue自动路由-单页面项目(非build时构建)
2019/04/30 Javascript
vue-router 中 meta的用法详解
2019/11/01 Javascript
js瀑布流布局的实现
2020/06/28 Javascript
vue 实现基础组件的自动化全局注册
2020/12/25 Vue.js
[53:20]2018DOTA2亚洲邀请赛 4.1 小组赛 A组加赛 VG vs OG
2018/04/03 DOTA
python基础while循环及if判断的实例讲解
2017/08/25 Python
python 处理dataframe中的时间字段方法
2018/04/10 Python
kaggle+mnist实现手写字体识别
2018/07/26 Python
python实现微信小程序自动回复
2018/09/10 Python
基于python实现学生管理系统
2018/10/17 Python
python requests.post带head和body的实例
2019/01/02 Python
从pandas一个单元格的字符串中提取字符串方式
2019/12/17 Python
python+selenium+chromedriver实现爬虫示例代码
2020/04/10 Python
css3实现波纹特效、H5实现动态波浪效果
2018/01/31 HTML / CSS
纽约的奢华内衣店:Journelle
2016/07/29 全球购物
法国创作个性化T恤衫和其他定制产品平台:Tostadora
2018/04/08 全球购物
英国电视和家用电器购物网站:rlrdistribution.co.uk
2018/11/20 全球购物
TOWER London官网:鞋子、靴子、运动鞋等
2019/07/14 全球购物
临床医学系毕业生推荐信
2013/11/09 职场文书
学校标语大全
2014/06/19 职场文书
宝宝满月宴答谢词
2015/09/30 职场文书
Python tensorflow卷积神经Inception V3网络结构
2022/05/06 Python