likes
comments
collection
share

03-纯函数、柯里化、组合函数

作者站长头像
站长
· 阅读数 27

纯函数

定义 1.相同的输入,相同的输出。 2.执行过程中不会产生副作用。

const letters = ['a', 'b', 'c'];
// 纯函数
letters.slice(1);
console.log(letters); // [ 'a', 'b', 'c' ]
// 产生副作用,非纯函数
letters.splice(1);
console.log(letters); // [ 'a' ]

柯里化

定义 只传递一部分参数给函数,返回一个接收剩余参数的函数,这个过程就是柯里化

让函数职责单一

function add(x, y, z) {
  x = x + 2;
  y = y * 2;
  z = z * z;
  return x + y + z;
}

console.log(add(10, 20, 30));

// 柯里化 
function sum(x) {
  x = x + 2;
  return function (y) {
    y = y * 2;
    return function (z) {
      z = z * z;
      return x + y + z;
    };
  };
}

console.log(sum(10)(20)(30));

代码的复用

const makeAdder = count => {
  return num => {
    return count + num;
  };
};

const adder5 = makeAdder(5);
console.log(adder5(10)); // 15
console.log(adder5(20)); // 25

柯里化函数的实现

// 接收一个函数,返回柯里化函数
function myCurrying(fn) {
  function curried(...args) {
    // 当传入参数少于原函数参数
    if (args.length < fn.length) {
      // 返回一个函数处理剩余参数
      return function (...args2) {
        // 剩余参数,拼接现有参数进行递归
        return curried.apply(this, args.concat(args2));
      };
    } else {
      // 直接调用,并绑定this
      return fn.apply(this, args);
    }
  }

  return curried;
}

function add(num1, num2, num3) {
  console.log(this);
  return num1 + num2 + num3;
}

const newFn = myCurrying(add);
console.log(newFn.call('abc', 10, 20, 30));
console.log(newFn(10, 20)(30));
console.log(newFn(10)(20)(30));

组合函数

定义 需要将多个函数依次执行。将这些函数组合起来,自动依次执行,这个过程就是函数的组合。

function double(num) {
  return num * 2;
}

function square(num) {
  return num ** 2;
}
// 假设需要先执行double
const res = square(double(10));
console.log(res);

// 组合函数的简单实现
function composeFn(fn1, fn2) {
  return function (count) {
    return fn2(fn1(count));
  };
}

const newFn = composeFn(double, square);
const res2 = newFn(20);
console.log(res2);

通用组合函数的实现

function add(num1, num2) {
  console.log(this);
  return num1 + num2;
}
function double(num) {
  console.log(this);
  return num * 2;
}
function square(num) {
  console.log(this);
  return num ** 2;
}

// 通用的组合函数实现
function myCompose(...fns) {
  if (!fns.length) {
    throw new TypeError('必须传入函数类型');
  }
  for (let fn of fns) {
    if (typeof fn !== 'function') {
      throw new TypeError('必须传入函数类型');
    }
  }

  // 返回一个自动依次执行的函数
  function composeFn(...args) {
    // 先执行一次
    let index = 0;
    let res = fns[index].apply(this, args);

    // 拿到上一次的结果调用下一个函数,获得新的结果
    while (++index < fns.length) {
      res = fns[index].call(this, res);
    }
    return res;
  }

  return composeFn;
}

const newFn = myCompose(add, double, square);
const res = newFn.call('call', 10, 20);
console.log(res);