函数柯里化

589 阅读2分钟

这是我参与更文挑战的第9天,活动详情查看:更文挑战

首先说一下为什么叫柯里化,完全是因为这个技术由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的。所以不必在意为什么叫这个名字,我们也可以记谐音颗粒化(将参数一个一个的传入)。

这个就是把接收多个参数的方法变换成接收单一参数的函数,并且返回接收剩余参数的一个新函数。

函数

先来看一个简单的函数

function multiply(x, y){
    return x * y;
}

multiply(2, 5); // 10

上面这个函数的主要作用就是将两个函数相乘。 接下来我们让这个函数变成只接受一个参数的函数,并且可以保存之前传入的值。

function curry_multiply(x, y) {
    return (y) => {
        return x * y;
    }
}

let multiply2 = curry_multiply(2);
multiply2(5); // 10

let multiply5 = curry_multiply(5);
multiply5(2); // 10

了解过闭包的就应该能看懂上面的函数,返回了一个新的函数,并且保存了x变量的值。这就使得我们传入curry_multiply的值可以保留下来,方便我们针对不同情况的调用。

下面介绍一个通用柯里化的函数,此函数只是一个简化版本,在实际应用中需要判断其他情况。

function curry(fn, ...args) {
		return (...arg) => {
			return fn(...args, ...arg);
		}
	}

function volumn(x, y, z) {
	return x*y*z;
}

let test2 = curry(volumn, 2);
let test10 = curry(test2, 5);
test10(10); // 100

curry函数的主要作用是将传入的第一个参数作为函数进行调用,将第二个参数作为fn的参数传入,并将剩余参数传入。这样我们可以简单的复用同一个函数的不同参数情况。

应用场景

用的比较多的就是可以复用大多数相似的函数功能,多参数的情况,可以封装一些多次用到的固有参数。

function checkPhone(phoneNumber) {
    return /^1[34578]\d{9}$/.test(phoneNumber);
}
function checkEmail(email) {
    return /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/.test(email);
}

上面这种应该在项目里面比较常见,可以用curry稍微优化一下。

let _check = createCurry(check);

let checkPhone = _check(/^1[34578]\d{9}$/);
let checkEmail = _check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/);