javascript高级 --- 函数柯里化

一、介绍
函数柯里化(currying)又称部分求值,一个currying函数首先接受一部分参数,该函数不会立即求值,而是返回另外一个函数(高阶函数),刚才传入的参数通过闭包存起来,当真正需要求值时,一次性返回。

二、案例
函数求值
普通函数

function add (x, y) {
	return x + y
}
add(1,2)

我们用柯里化实现

function add(x) {
	return function (y) {
		return x + y
	}
}
add(1)(2) // 3

可以看到当我们传入第一个参数时,会返回一个新的函数去处理剩下的参数

利用箭头函数会更清晰

let add x => y => x + y
add(1)(2) // 3

三、封装

我们写一个柯里化的通用版本

let currying = function (fun) {
	// arguments是一个类数组,需要转成真实数组
	let args = Array.prototype.slice.call(arguments,1)
	return function () {
		let _args = Array.prototype.sliice.call(arguments)
		fun.apply(this,args.concat(_args))		
	}
}

function add (...args) {
	let result = args.reduce((total,item) => total + item , 0)
	console.log(result)
}

let _add = currying(add,1,2)
_add(3,4) // 10

通过上面代码我们发现,柯里化之后,_add函数只能执行一次,如果我们想多次执行_add(1)(2)(3),会报错,因为我们返回一个值,而不是一个函数。

类似情况,我们首先想到采用递归的方式,如果currying之后调用的函数有参数,我们就继续递归执行,反之执行结束

let currying = function (fun, arr = []) {
	// 取出执行时参数,首次执行截掉function
	let args = Array.prototype.slice.call(arguments,1) || arr
	// 闭包 保存结果
	return function () {
		// 再次调用时的参数
		let _args = Array.prototype.slice.call(arguments)
		// 如果参数不存在,执行函数,反之继续递归执行
		if (_args.length == 0){
			return fun.apply(this,args.concat(_args))
		}else {
			return currying.call(this,fun,...args.concat(_args))
		}
	}
}

function add (...args) {
	let result = args.reduce((total,item) => total + item , 0)
	console.log(result)
}

let _add = currying(add)
_add(2)(5)(8)(1)() // 16
_add(2,5,8)(1)() // 16

以上就是函数柯里化的内容了,理解起来比较费劲,编程思想很赞!

注意:

1、arguments是一个类数组(非数组对象),需要用Array.prototype.slice.call(arr)转成真数组,也可以使用ES6提供的Array.from()处理: Array.prototype.slice.call(arr) === Array.form()
2、ES6规定function可以有length,代表当前函数的参数数量,如果参数设置默认值或者使用扩展运算符,length为0 (…args / args = [])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端小小白zyw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值