felix-cao / Blog

A little progress a day makes you a big success!
31 stars 4 forks source link

JavaScript 的函数柯里化(currying) #116

Open felix-cao opened 5 years ago

felix-cao commented 5 years ago

一、柯里化简述

柯里化是函数式编程两个最基本的运算之一

在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家哈斯凯尔·加里命名的,尽管它是 Moses SchönfinkelGottlob Frege 发明的。

// 普通的 add 函数
function add(x, y) {
    return x + y
}

// Currying 后
function curryingAdd(x) {
    return function (y) {
        return x + y
    }
}

add(1, 2)           // 3
curryingAdd(1)(2)   // 3

实际上就是把 add 函数的 x,y 两个参数变成了先用一个函数 curryingAdd 来接收 x 然后返回一个匿名函数去处理 y 参数。

简单来说就是只传递给函数一个参数来调用它,让它返回一个函数去处理剩下的参数。

二、使用场景

2.1、 参数复用

即减少重复传递不变的部分参数, 如下面的函数 simpleURL 生成一个完成的 url 并调用

function simpleURL(protocol, domain, path) {
    return protocol + "://" + domain + "/" + path;
}

var myurl = simpleURL('http', '56512.com', '');
var myurl2 = simpleURL('http', '56512.com', 'aboutme.html');

我们发现前两个参数保持不变,但每次调用都需要传递。所以可以对其优化,仅传递最后一个变化的参数。

function simpleURL(path) {
   return "http://56512.com/" + path;
}

然而还是有点缺陷,如果需要处理 https.cn 的请求呢。难道要改回去?若系统中已经大面积的使用了该代码,其向后兼容性就很差。针对这种情况,使用柯里化函数可以完美解决。

使用 lodash.curry 库函数使函数柯里化

// 避免每次调用重复传参
let myURL = _.curry(simpleURL);
let res1 = myURL('https', '56512.com')('home.html'); 

console.log(res1); // https://56512.com/home.html

let res2 = myURL('https')('56512.com')('home.html')
console.log(res2); // https://56512.com/home.html

Reference