# 纯函数、柯里化、偏应用、compose

# 纯函数

给定的输入总是返回相同的输出。 也就是函数的返回只依赖于它的参数 产生可测试的代码, 纯函数不应该改变任何外部环境的变量,函数执行过程没有副作用 合理的代码,必须具有一个有意义的名称, 通过函数名可以轻易的知道函数的作用 js不是一种纯函数语言

// 这个就是纯函数
function priceAfterTax(price) {
  return price * 1.2;
}

// 非纯函数 输出依赖外部变量tax
var tax = 0.2;
function priceAfterTax(price) {
  return price * (1 + tax);
}

# 柯里化

高阶函数和闭包构成柯里化函数

把一个多参数函数转换为一个嵌套的一元函数的过程

参数顺序

curry函数应用参数列表的顺序应该是从左到右

function curry(fn, ...args) {
  return function (...args2) {
    return fn(...args, ...args2);
  };
}

function sum(a, b, c) {
  return a + b + c;
}

const sumWith100 = curry(sum, 100);
console.log(sumWith100(1, 2));

// 参数不定长
function curry2(fn) {
  let params = [];
  return function anonymous(...args) {
    params = [...params, ...args];
    if (args.length === 0) {
      return fn.apply(null, params);
    } else {
      return anonymous;
    }
  };
}

const curry2Sum = curry2(sum);
console.log(curry2Sum(1)(2, 3)());

// 参数定长
function curry3(fn) {
  return function anonymous(...args) {
    if (args.length < fn.length) {
      return function () {
        return anonymous(...args, ...arguments);
      };
    }
    return fn(...args);
  };
}

# 偏应用(偏函数)

柯里化的参数顺序一般是从左到右, 但有时候我们需要颠倒参数的顺序。

先用一个undefined参数占住位置

// 偏函数
const partial = function (fn, ...partialArgs) {
  let args = partialArgs;
  // args = [undefined, 1000]
  return function (...fullArguments) {
    let j = 0;
    for (let i = 0; i < args.length && j < fullArguments.length; i++) {
      if (args[i] === undefined) {
        args[i] = fullArguments[j];
        j++;
      }
    }
    return fn.apply(null, args);
  };
};
// setTimeout的第一个参数暂时默认设置为undefined
let delayTimMsg = partial(setTimeout, undefined, 10);
delayTimMsg(() => {
  console.log('1000s');
});

# compose 函数组合

前一个函数的返回值作为参数传入后面的函数。 比如Redux的中间件就是这个原理

function compose(...funcs) {
  return funcs.reduce((a, b) => {
    return function (...args) {
      return a(b(...args));
    };
  });
}

function compose2(...funcs) {
  return function (...args) {
    const funcList = [...funcs];
    let result = funcList.pop()(...args);
    for (let i = funcList.length - 1; i >= 0; i--) {
      result = funcList[i](result);
    }
    return result;
  };
}
上次更新: 1/22/2025, 9:39:13 AM