关于前端:RxJS-与-函数式编程-函数式编程

前言

这是一个新的系列,记录本人学习 RxJS 以及函数式编程的过程。
这个系列的目标一个是作为笔记记录,另一个是心愿看到这个系列的你能对 RxJS 和函数式编程提起趣味学习/应用起来。

系列的外围是记录本人学习 RxJS 的过程,然而学习它不可避免的要学习函数式编程,本篇文章将着重记录函数式编程。

函数式编程

已经很长一段时间我都认为函数式编程就是应用函数解决问题的编程形式,学习了 RxJS 之后这个观点产生了天翻地覆的变动。

首先扭转我观点的是函数式编程固有的特点:

  • 申明式 (Declarative)
  • 纯函数 (Pure Function)
  • 数据不可变性 (Immutability)

申明式

往往解释一个概念最简略的形式就是解释它的对抗概念。
申明式编程的对抗概念应该是命令式编程,举一个生存中的例子 打车:

  • 命令式:

    • 上车
    • 路口右转
    • 直行500米
    • 路口左转
    • 阿巴阿巴…
    • 到站下车
  • 申明式:

    • 上车
    • 司机徒弟我要去XXX广场,而后开始玩手机
    • 到站下车

而后举一个代码的例子 实现一个函数参数为一个数组要求函数将数组的每一项数值都乘以2:

function double(arr) {
  const result = []
  for (let i = 0; i < arr.length; i++) {
    const item = arr[i]
    result.push(item * 2)
  }
  return result
}

下面的实现属于典型的命令式编程格调,其本质就是通知计算机整个性能的实现所须要的计算逻辑,而他的对立面申明式编程的代码是这样:

function double(arr) {
  return arr.map(item => item * 2)
}

如果应用箭头函数代码能够更加简洁:

const double = arr => arr.map(item => item * 2)

纯函数

讲纯函数我认为必须先抛出许多人写代码可能呈现的“问题” 还是以 double 函数举例:

function double(arr) {
  for (let i = 0; i < arr.length; i++) {
    const item = arr[i]
    arr[i] = item * 2
  }
  return arr
}

const originalArray = [1, 2, 3]
const result = double(originalArray)

请问上述代码 result 值是什么。

这时候应该要脱口而出 [2, 4, 6],然而对应的 originalArray 值是什么呢?

这里 originalArray 的值是 [2, 4, 6],单从 “性能是否实现” 的角度看,这里 double 的实现没有任何问题,可是作为开发者的你是否会抉择应用这种实现形式的函数呢?或者作为开发者的你是否常常写这种函数呢?

这里的这种函数称之为 “不纯函数 (Impure Function)” 相同前一大节写的那两个 double 函数都是纯函数。不纯函数的特点:

  • 扭转全局变量
  • 扭转传入参数
  • 抛出异样
  • 操作 DOM
  • 读取用户输出
  • 网络的输出/输入,比方AJAX

扯了这么多就是想表白一句话:
纯函数做的事就是给我雷同的输出参数,我始终返给你雷同的输入,并且这个过程没有副作用(让我想起了 React.useEffect)产生。

最初多说一句,纯函数非常容易些单元测试。

数据不可变性

数据不可变的重要性其实在下面 纯函数 的例子中曾经有了体现,double 函数批改了传入参数,导致 originalArray 产生了变动产生副作用,这种相似的问题引发了数不清的 bug。

怎么实现数据的不可变性也是一个重要的内容,可能波及到深浅拷贝、immutable.js 等,先不开展了当前聊(我懒)。

多嘴提一句,JavaScript 中的 const 关键字只是规定一个变量的 援用 不可扭转,所以 const 定义的变量严格讲不全属于不可变数据。

结语

对于函数式编程的内容本篇介绍只是冰山一角,但思考到这个系列的外围是讲 RxJS 就不再深挖了(多的不会了)。

下一篇开始讲 RxJS。


评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理