柯里化介绍

函数柯里化指的是函数处理一部分的参数,然后返回一个函数来处理剩余的参数,如比如有一个加法函数如下

  1. function add(x, y) {
  2. return x + y;
  3. }
  4. add(1, 2); // 3

现在如果这个函数被柯里化,那么我们可以如下使用

  1. const increment = add(1); // 接收第一个参数,返回一个函数处理第二个参数
  2. increment(2); // 3
  3. increment(4); // 5

柯里化实现

现在怎么实现这种效果,如果只是针对上面的加法函数,那么可以如下实现

  1. function add(x, y) {
  2. return function(y) {
  3. return x + y;
  4. }
  5. }

但是这种方法明显只对加法函数有效,我们现在是想设计一个函数,它接收一个函数为参数,作用就是把这个函数柯里化,并将这个柯里化的函数返回,比如

  1. curryAdd = curry(add); // 接收add函数,将函数add柯里化
  2. const increment = curryAdd(1);
  3. increment(2); // 3
  4. increment(4); // 5

首先实现一个简单版本的

  1. function curry(fn, ...args1) {
  2. return function(...args2) {
  3. fn(...args1, ...args2)
  4. }
  5. }

但是这个函数明显有一个缺陷,那就是只能传入两次参数,怎么解决,肯定使用递归了

  1. function curry(fn, ...args1) {
  2. if (fn.length == args1.length) {
  3. return fn(...args1);
  4. } else {
  5. return function(...args2) {
  6. return curry(fn, ...args1, ...args2)
  7. }
  8. }
  9. }

上面的函数首先判断接收的参数的个数与函数要求参数的个数是否相同,如果相同则直接执行函数,否则返回一个函数来处理剩下的参数,这样就可以实现函数的柯里化。

柯里化应用举例

现在来看一下柯里话用什么用处,假设有一个 ajax 请求的函数如下

  1. function ajax(type, url, data) {
  2. let xhr = new XMLHttpRequest();
  3. xhr.onReadystateChange = function() {
  4. // ...
  5. }
  6. xhr.open(type, url);
  7. xhr.send(data);
  8. }

现在我们将这个函数柯里化

  1. let curriedAjax = curry(ajax);
  2. let post = curriedAjax('post');

我们向 curriedAjax 传入一个参数 post,得到一个函数,这个函数的作用是用来发 post 请求的,我们每次发 post 请求时,只需要使用 post 方法即可,这样函数的复用性有了极大的增强,我们可以继续传入参数

  1. let postGoogle = post('https://www.google.com');

我们又得到了一个函数,该函数的作用是向 https://www.google.com 发送 post 请求,函数的复用性又进一步的提升。

使用过jQuery的都知道,可以使用$.ajax()这样的通用方法,但是也有$.get()$.post()这样的语法糖,但是jQuery底部是不是这样实现的就不得而知了。

参考链接