柯里化
柯里化函数:将一个多元函转换成依次调用的单元函数
const _ = require('lodash')
// 要柯里化的函数
function getSum (a, b, c) {
return a + b + c
}
// 柯里化后的函数
let curried = _.curry(getSum)
// 测试
console.log(curried(1, 2, 3)) //6
console.log(curried(1)(2)(3)) //6
console.log(curried(1, 2)(3)) //6
用途
function ajax(){...}
// 虽然 ajax 这个函数非常通用,但在重复调用的时候参数冗余
ajax('POST', 'www.test.com', "name=kevin")
ajax('POST', 'www.test2.com', "name=kevin")
ajax('POST', 'www.test3.com', "name=kevin")
// 利用 curry
var ajaxCurry = curry(ajax);
// 以 POST 类型请求数据
var post = ajaxCurry('POST');
post('www.test.com', "name=kevin");
// 以 POST 类型请求来自于 www.test.com 的数据
var postFromTest = post('www.test.com');
postFromTest("name=kevin");
curry 的这种用途可以理解为:参数复用。本质上是降低通用性,提高适用性。
同样也可以将柯里化后的函数传给map:
var person = [{name: 'kevin'}, {name: 'daisy'}]
var name = person.map(function (item) {
return item.name;
})
var prop = curry(function (key, obj) {
return obj[key]
});
var name = person.map(prop('name'))
console.log(name)
//[ 'kevin', 'daisy' ]
仿写
接下来模拟下模拟下curry函数:
function curry (func) {
return function curriedFn (...args) {
if (args.length < func.length) {
return function () {
return curriedFn(...args.concat(Array.from(arguments)))
}
}
return func(...args)
}
}
这个函数首先返回一个函数,以便接受后续参数,先判断形参与实参的数量,假如实参和形参数量相同,就直接执行func()并返回,假如不等,就返回一个函数,并将实参返回出去,这里就形成了一个闭包,这里将实参存储起来,通过Array.concat函数将实参依次连接起来,直到实参等于形参,再执行func()。这也算是闭包的一个运用场景。
偏函数
在计算机科学中,偏函数是指固定一个函数的一些参数,然后产生另一个更小元的函数。
什么是元?元是指函数参数的个数,比如一个带有两个参数的函数被称为二元函数。
const _ = require('lodash')
function add(a, b) {
return a + b;
}
// 执行 add 函数,一次传入两个参数即可
add(1, 2) // 3
var addOne = _.partial(add, 1);
console.log(addOne(2)) // 3
跟柯里化是很像的,但还是有些区别的:
柯里化是将一个多参数函数转换成多个单参数函数,也就是将一个 n 元函数转换成 n 个一元函数。
偏函数则是固定一个函数的一个或者多个参数,也就是将一个 n 元函数转换成一个 n - x 元函数。
仿写
function partial(fn) {
var args = [].slice.call(arguments, 1);
return function() {
var newArgs = args.concat([].slice.call(arguments));
console.log(arguments)
return fn.apply(this, newArgs);
};
};