浅析JavaScript 函数柯里化

 更新时间:2020年09月08日 09:16:28   作者:前端开发  
这篇文章主要介绍了JavaScript 函数柯里化的相关资料,帮助大家更好的理解和学习JavaScript,感兴趣的朋友可以了解下

柯里化 (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的原型与原型链

    这篇文章主要为大家详细介绍了JavaScript原型与原型链,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • javascript容错处理代码(屏蔽js错误)

    javascript容错处理代码(屏蔽js错误)

    本文主要介绍了javascript的容错处理代码。具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • three.js简单实现类似七圣召唤的掷骰子

    three.js简单实现类似七圣召唤的掷骰子

    这篇文章主要为大家介绍了three.js简单实现类似七圣召唤的掷骰子示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • js控制的回到页面顶端goTop的代码实现

    js控制的回到页面顶端goTop的代码实现

    在浏览网页的时候应该会经常见到右下角有个【回到顶端】的悬浮东东,本文也要使用js实现一下,感兴趣的朋友可以参考下哈,希望可以帮助到你
    2013-03-03
  • js对象的读取速度实例详解

    js对象的读取速度实例详解

    在本篇文章里小编给大家整理了一篇关于js对象的读取速度实例详解内容,有需要的朋友们可以跟着学习下。
    2021-11-11
  • 使用伪命名空间封装保护独自创建的对象方法

    使用伪命名空间封装保护独自创建的对象方法

    下面小编就为大家带来一篇使用伪命名空间封装保护独自创建的对象方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08
  • js使用canvas实现绘制月饼

    js使用canvas实现绘制月饼

    皓月当空,月圆中秋,在这个传统节日里,除了赏月、猜灯谜、赏花灯等习俗外,还有就是品尝美味的月饼,本文就来使用canvas绘制一个精美的月饼吧
    2023-09-09
  • 原生js和jQuery随意改变div属性style的名称和值

    原生js和jQuery随意改变div属性style的名称和值

    用原生js和jQuery实现改变随意改变div属性style的名称和值的结果,这个实例比较实用,新手朋友们可以看看
    2014-10-10
  • TypeScript声明文件的语法与场景详解

    TypeScript声明文件的语法与场景详解

    使用ts进行开发的时候,不可避免的需要引用第三方的 JS 的库,但是默认情况下TS是不认识我们引入的这些JS库的,所以在使用这些JS库的时候,我们就要通过声明文件告诉TS它是什么,这篇文章主要给大家介绍了关于TypeScript声明文件的相关资料,需要的朋友可以参考下
    2022-05-05
  • uniapp中renderjs使用与传值问题

    uniapp中renderjs使用与传值问题

    renderjs是一个运行在视图层的js,它只支持app-vue和h5,下面这篇文章主要给大家介绍了关于uniapp中renderjs使用与传值问题的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-07-07

最新评论