纯函数 - 柯里化 - 组合

纯函数

  • 什么是纯函数?

    • 确定的输入,一定会产生确定的输出

    • 函数在执行过程中,不能产生副作用

  • 什么是副作用?

    • 在执行一个函数时,除了返回值函数之外,还对调用函数产生了附加的影响,比如说修改了全局变量,修改参数或者改变外部的存储
  • 纯函数例子

    var names = ["abc", "cba", "nba", "dna"]
    // slice只要给它传入一个start/end, 那么对于同一个数组来说, 它会给我们返回确定的值
    // slice函数本身它是不会修改原来的数组
    // 所以slice函数本身就是一个纯函数
    var newNames1 = names.slice(0, 3)
    console.log(newNames1)

    // splice不是一个纯函数
    var newNames2 = names.splice(2)
    console.log(newNames2)
    console.log(names) // [ 'abc', 'cba' ] 改变了原数组

JavaScript柯里化

  • 什么是柯里化?

    • 把接收多个参数的函数变成接收一个单一参数的函数
    • “如果你固定某些参数,你将得到接受余下参数的一个函数”
    • 只传递给函数一部分参数来调用它,让它返回一个函数去处理剩余的参数,这个过程称之为柯里化
  • 柯里化的结构

    function add(x, y, z) {
    return x + y + z
    }
    var result = add(10, 20, 30)
    console.log(result); // 60

    function sum1(x) {
    return function(y) {
    return function(z) {
    return x + y + z
    }
    }
    }

    var result2 = sum1(10)(20)(30) // 60
    console.log(result2);

    // 简化
    var sum2 = x => y => z => x + y + z
  • 柯里化让函数的职责单一

    每次接收的一个参数,都做它自己的逻辑

  • 可以更好的复用参数逻辑

    function makeAdder(count) {
    count = count * count

    return function(num) {
    return count + num
    }
    }

    // 比如说我们想要每次的count都是5
    var adder5 = makeAdder(5)
    adder5(10)
    adder5(13)
  • 柯里化函数的实现

    function myCurrying(fn) {
    function curried(...args) {
    // 当已经传入的参数 大于等于 需要的参数时, 就执行函数
    if (args.length >= fn.length) {
    // fn()
    return fn.apply(this, args)
    } else {
    // 没有达到个数时, 需要返回一个新的函数,继续来接收参数
    function curried2(...args2) {
    // 接收到参数后, 需要递归调用curried来检查函数的个数是否达到
    return curried.apply(this, [...args, ...args2])
    }
    return curried2
    }
    }

    // 返回一个柯里化的函数
    return curried
    }

    function add1(x, y, z) {
    return x + y + z
    }

    var curryAdd = myCurrying(add1)
    console.log(curryAdd(10, 20, 30));
    console.log(curryAdd(10)(20, 30));
    console.log(curryAdd(10)(20)(30));

组合函数

  • 什么是组合函数?

    • 组合函数是在 JavaScript 开发过程中一种对函数的使用技巧、模式
  • 组合函数的例子

    function double(num) {
    return num * 2
    }

    function square(num) {
    return num ** 2
    }

    var count = 10
    var result = square((double(count)))
  • 实现组合函数

    function hyCompose(...fns) {
    // 如果不是函数,直接报错
    let length = fns.length
    for (let i = 0; i < length; i++) {
    if(typeof fns[i] !== 'function') {
    throw new TypeError('Expected a function')
    }
    }

    // 取出所有的函数一次调用
    return function(...args) {
    let index = 0
    let result = length ? fns[index].apply(this, args) : args
    while(++index < length) {
    result = fns[index].call(this, result)
    }
    return result
    }
    }

    function double(m) {
    return m * 2
    }

    function square(n) {
    return n ** 2
    }

    let newFn = hyCompose(double, square)
    console.log(newFn(10))