JS函数式编程?我对函数式编程的理解和看法

372 阅读3分钟

今年JS最大的热点恐怕就是函数式编程了,不管是像我这种小菜鸟还是大佬们都在议论纷纷。我自己呢,通过网上合理冲浪也学习到了一些函数式编程的理念以及看法。

首先在目前个人从各方面学习到的知识得出:JS是不可能实现完全的函数式编程的,但是在JS当中函数也是一等公民,所以我们大可不必深究所谓的函数式细则,不同国家都有不同国情 何况是语言呢?取长补短 我们只需利用函数时编程的一些理念进行开发即可。

函数式编程中有一个非常重要的概念叫纯函数,JavaScript符合函数式编程的范式,所以也有纯函数的概念

那么什么是纯函数呢?

总结如下:

  1. 确定的输入 一定会返回确定的输出
  2. 函数在执行过程中,不能产生副作用

我们直接用Array中的方法进行举例子

Array.slice 在执行过程中,只要有确定的输入 ,它永远都会返回确定的输出结果 且不会改变原数组本身,所以slice是个纯函数实现

Array.splice 在执行过程中,虽然在确定的输入,它也会返回确定的输出,但是对原数组进行了修改,产生了副作用。所以他不能称为纯函数。

上文输出的纯函数概念到底有什么好处呢? 好处就一句话,我们可以安心的编写,放心的用。熟悉react的朋友,react虽然很灵活 但是一直有一条很严格的规则,React中就要求我们无论是函数还是class声明一个组件,这个组件都必须像纯函数一样,保护它们的props不被修 改。

JS的函数式编程还有一个重要概念 就是柯里化

柯里化的解释 维基百科中就描述的非常清除了:是把接收多个参数的函数,变成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参 数,而且返回结果的新函数的技术就称为柯里化

柯里化的作用就是逻辑复用和让各个函数分工明确 让一个函数处理的问题尽可能的单一,而不是将一大堆的处理过程交给一个 函数来处理

// 普通函数
function add (a, b, c) {
 return a + b + c
}
add(1,2,3)
// 柯里化
let add = (a) => (b) => (c) => a + b + c
add(1)(2)(3)
// 自动柯里化函数
    function currying(fn) {
      return function curried(...args) {
        if (args.length >= fn.length) {
          return fn.apply(this, args)
        } else {
          return function(...args2) {
            return curried.apply(this, args.concat(args2))
          }
        }
      }
    }
    function add(a, b, c) {
      return a + b + c
    }
    let sum = currying(add)(1, 2)(3)
    console.log("sum", sum)

组合函数是在JavaScript开发过程中一种对函数的使用技巧

比如我们现在需要对某一个数据进行函数的调用,执行两个函数fn1和fn2,这两个函数是依次执行的; 那么如果每次我们都需要进行两个函数的调用,操作上就会显得重复;

可以将这两个函数组合起来,自动依次调用呢

// 组合函数
    function compose(...fns) {
      const length = fns.length
      for (let i = 0; i < length; i++) {
        if (typeof fns[i] !== "function") {
          throw new TypeError("expected are 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 add(a) {
      return a + 1
    }
    function double(a) {
      return a * a
    }
    let foo = compose(add, double)(5)
    console.log(foo)