每周分享:函数式编程之递归模式

函数式编程(FP)就是利用纯函数来构建软件的过程,避免共享状态,可变数组以及一些副作用。而 ES6 带来了很多的特性帮助我们更方便地进行 JavaScript 函数式编程。

今天我们就来看看 ES6 的剩余参数语法结合递归实现如何实现函数式编程,用函数式思想实现一些我们常用的方法。

返回数组的第一个元素

const head = ([x]) => x

使用

const arr = [1, 2, 3]
head(arr) // 1

Tail

返回数组中除第一个元素外的其它元素

const tail = ([, ...xs]) => xs

上面写法中省略了第一个参数,所以也等价于

const tail = ([x, ...xs]) => xs

使用

const arr = [1, 2, 3]
tail(arr) // [2, 3]

Def

如果存在参数则返回 true,否则返回 false

const def = x => typeof x !== "undefined"

使用

const name = "tom"
def(name) // true
def(age) // false

Copy

复制数组

const copy = arr => [...arr]

使用

let arr = [1, 2, 3]
let copied = copy(arr)
copied.push(4)
arr // [1, 2, 3]
copied // [1, 2, 3, 4]

Reverse

反转数组

const reverse = ([x, ...xs]) => def(x) ? [...reverse(xs), x] : []

这里我们通过递归依次将整个数组给调换顺序了,使用

const arr = [1, 2, 3]
reverse(arr) // [3, 2, 1]

First

返回一个新的数组,包含给定数组前 n 项的元素

const first = ([x, ...xs], n = 1) => def(x) && n ? [x, ...first(xs, n - 1)] : []

同样运用了递归的思想,使用

const arr = [1, 2, 3]
first(arr, 2) // [1, 2]

计算过程如下

  • 首先 first(arr, 2) = first([1, 2, 3], 2)
  • def(x) = def(1) && n = 2 => true
  • 返回 [x, ...first(xs, n - 1)] = [1, ...first([2, 3], 1)]
  • 计算 first([2, 3], 1)
  • def(x) = def(2) && n = 1 => true
  • 返回 [x, ...first(xs, n - 1)] = [2, ...first([3], 0)]
  • 计算 first([3], 0)
  • def(x) = def(3) && n = 0 => false
  • 于是 first([3], 0) 返回 []
  • 所以结果为 [1, ...[2, ...[]]] => [1, 2]

Last

返回一个新的数组,包含给定数组后 n 项的元素

const last = (xs, n = 1) => reverse(first(reverse(xs), n))

结合上面的 first 方法和反转,使用

const arr = [1, 2, 3]
last(arr, 2) // [2, 3]

本期的主要目的不是为了让大家在实际开发中就这样去上面的方法,实际上数组也提供了相应的便捷方法,之所以讲这些,是为了让大家更加深刻理解函数式编程的纯函数特性。

最新评论

  1. Thanks , I’ve recently been searching for info approximately this topic for
    ages and yours is the best I’ve came upon till now.
    But, what about the bottom line? Are you positive in regards to the source?

sikis进行回复 取消回复

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