JavaScript 系列之闭包(三)

这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战前端

5、柯里化

柯里化(Currying)是把接受多个参数的函数转变为单一参数的函数,而且返回接受余下的参数且返回结果的新函数的技术。面试

简单来讲:segmentfault

  1. 经过闭包管理
  2. 支持链式调用
  3. 每次运行返回一个 function

即:经过将多个参数换成一个参数,每次运行返回新函数的技术markdown

5.1 柯里化举例

// 普通的 add 函数
function add (a, b) {
  return a + b;
}
add(1, 2);
复制代码
// 柯里化函数
function curryingAdd (x) {
  return function(y) {
    return x + y;
  }
}
curryingAdd(x)(y);
复制代码

5.2 柯里化好处

  1. 参数复用
  2. 提早确认
  3. 延迟运行
// 校验数字
let numberReg = /[0-9]+/g;

// 校验小写字母
let stringReg = /[a-z]+/g;

// currying 后
function curryingCheck(reg) {
  return function(txt) {
    return reg.test(txt);
  }
}


let checkNumber = curryingCheck(numberReg);
let checkString = curryingCheck(stringReg);


console.log(checkNumber('13888888888')); // true
console.log(checkString('jsliang')); // true
复制代码

5.3 柯里化实现 add(1)(2)(3)

// 实现一个 add 方法,使计算结果可以知足如下预期
add(1)(2)(3) = 6;
add(1, 2, 3)(4) = 10;
add(1)(2)(3)(4)(5) = 15;
复制代码
function add () {
  const numberList = Array.from(arguments);

  // 进一步收集剩余参数
  const calculate = function() {
    numberList.push(...arguments);
    return calculate;
  }

  // 利用 toString 隐式转换,最后执行时进行转换
  calculate.toString = function() {
    return numberList.reduce((a, b) => a + b, 0);
  }

  return calculate;
}

// 实现一个 add 方法,使计算结果可以知足如下预期
console.log(add(1)(2)(3)); // 6
console.log(add(1, 2, 3)(4)); // 10;
console.log(add(1)(2)(3)(4)(5)); // 15;
console.log(add(1)(2)(3)(4)(5, 6, 7)); // 28
复制代码

5.4 柯里化实现 compose(foo, bar, baz)('start')

function foo(...args) {
  console.log(args[0]);
  return 'foo';
}
function bar(...args) {
  console.log(args[0]);
  return 'bar';
}
function baz(...args) {
  console.log(args[0]);
  return 'baz';
}

function compose() {
  // 闭包元素 - 函数列表
  const list = Array.from(arguments);

  // 闭包元素 - 函数列表执行位置
  let index = -1;

  // 闭包元素 - 上一个函数的返回
  let prev = '';

  // 返回闭包函数
  const doNext = function() {
    index++; // 索引值累加
    // 一开始没有上一个元素时,获取第二个括号的值
    if (!prev) {
      prev = arguments[0];
    }
    // 设置前一个结果为当前函数返回
    prev = list[index](prev);
    // 递归调用
    if (index < list.length - 1) {
      doNext(index + 1);
    }
  };

  // 第一次返回闭包函数
  return doNext;
}

compose(foo, bar, baz)('start');
复制代码

相关好文

相关文章
相关标签/搜索