请选择 进入手机版 | 继续访问电脑版

JavaScript函数式编程简介

前端开发  / Javascript  / 倒序浏览   © 著作权归作者本人所有

#楼主# 2020-5-17

跳转到指定楼层

JavaScript编程语言中的函数式编程的主要概念入门

函数式编程简介

函数式编程(FP)是具有某些特定技术的编程范例。

在编程语言中,您会发现纯函数式编程语言以及支持函数式编程技术的编程语言。

Haskell,Clojure和Scala是一些最受欢迎的纯函数式编程语言。

支持功能编程技术的流行编程语言是JavaScript,Python,Ruby和许多其他语言。

函数式编程不是一个新概念,实际上其起源可以追溯到lamda演算的1930年代,它影响了许多编程语言。

FP最近获得了很大的发展动力,所以现在是学习它的最佳时机。

在本课程中,我将通过在代码示例中使用JavaScript来介绍函数式编程的主要概念。

一流的功能

在函数式编程语言中,函数是一等公民。

可以将它们分配给变量

const f = (m) => console.log(m)
f('Test')

由于函数可以分配给变量,因此可以将它们添加到对象中:

const obj = {
  f(m) {
    console.log(m)
  }
}
obj.f('Test')

以及数组:

const a = [
  m => console.log(m)
]
a[0]('Test')

它们可以用作其他函数的参数

const f = (m) => () => console.log(m)
const f2 = (f3) => f3()
f2(f('Test'))

它们可以通过函数返回

const createF = () => {
  return (m) => console.log(m)
}
const f = createF()
f('Test')

高阶函数

接受函数作为参数或返回函数的函数称为高阶函数

在JavaScript标准库的例子包括Array.map()Array.filter()并且Array.reduce(),我们将在一个位见。

声明式编程

您可能已经听说过“声明式编程”一词。

让我们将该术语放在上下文中。

的相反的声明势在必行

声明式与命令式

当您告诉机器(一般而言)时,完成工作所需采取的步骤是当务之急。

声明性方法是当您告诉机器您需要做什么时,让它弄清楚细节。

当您具有足够的抽象级别来停止推理低级构造时,就开始考虑声明式,而在较高的UI级别上要考虑更多。

有人可能会说C编程比Assembly编程更具声明性,这是事实。

HTML是声明性的,因此,如果您自1995年以来就一直使用HTML,那么实际上您已经从20多年来开始构建声明性UI。

JavaScript可以采用命令式和声明式编程方法。

例如声明性编程的方法是避免使用循环,而使用函数式编程结构,如mapreducefilter,因为你的程序是比较抽象的,少集中在告诉机器加工的每个步骤。

不变性

在功能编程中,数据永不变。数据是不可变的

变量永远不能更改。要更新其值,请创建一个新变量。

要添加新项,而不是更改数组,您可以通过串联旧数组和新项来创建新数组。

对象从不更新,但在更改之前先进行复制。

const

这就是为什么ES2015 const在现代JavaScript中如此广泛使用的原因,它包含了功能性编程概念:强制变量保持不变。

Object.assign()

ES2015还给了我们[Object.assign(),这是创建对象的关键:

const redObj = { color: 'red' }
const yellowObj = Object.assign({}, redObj, {color: 'yellow'})

concat()

为了将项目附加到JavaScript中的数组中,我们通常push()在数组上使用方法,但是该方法会更改原始数组,因此它不支持FP。

相反,我们使用以下concat()方法:

const a = [1, 2]
const b = [1, 2].concat(3)
// b = [1, 2, 3]
const c = [...a, 3]
// c = [1, 2, 3]

filter()

从数组中删除项目也是如此:代替使用pop()splice()修改原始数组,请使用array.filter()

const d = a.filter((v, k) => k < 1)
// d = [1]

纯度

一个纯函数

  • 永远不要更改通过引用传递给它的任何参数(在JS,对象和数组中):应将它们视为不可变的。当然,它可以更改按值复制的任何参数
  • 纯函数的返回值不受其输入参数的影响:传递相同的参数始终会导致相同的输出
  • 在执行过程中,纯函数不会更改其外部的任何内容

数据转换

由于不变性是一个非常重要的概念,也是函数式编程的基础,因此您可能会问如何改变数据。

简单:通过创建副本即可更改数据

函数特别是通过返回新的数据副本来更改数据。

做到这一点的核心功能是mapreduce

Array.map()

调用Array.map()数组将创建一个新数组,并在原始数组的每个项目上执行一个函数的结果:

const a = [1, 2, 3]
const b = a.map((v, k) => v * k)
// b = [0, 2, 6]

Array.reduce()

调用Array.reduce()数组可以使我们将数组转换成其他任何形式,包括标量,函数,布尔值,对象。

您传递一个处理结果的函数和一个起点:

const a = [1, 2, 3]
const sum = a.reduce((partial, v) => partial + v, 0)
// sum = 6
const o = a.reduce((obj, k) => { obj[k] = k; return obj }, {})
// o = {1: 1, 2: 2, 3: 3}

递归

递归是函数式编程中的关键主题。当函数调用自身时,它称为递归函数

递归的经典示例是斐波那契数列(N =(N-1 + N-2))计算,此处使用其2 ^ N完全无效(但易于阅读)的解决方案:

var f = (n) => n <= 1 ? 1 : f(n-1) + f(n-2)

组成

组合是函数式编程的另一个关键主题,这是将其纳入“关键主题”列表的充分理由。

组合是我们通过组合更简单的函数来生成高阶函数的方式

用普通JS编写

在普通JavaScript中组成函数的一种非常常见的方法是将它们链接起来:

obj.doSomething()
   .doSomethingElse()

或者,也非常广泛地使用,通过将函数执行传递给函数:

obj.doSomething(doThis())

借助 lodash

更一般地,组合是将许多功能的列表放在一起以执行更复杂的操作的动作。

lodash/fp带有以下实现compose:我们执行一系列函数,从一个参数开始,每个函数都从先前的函数返回值继承该参数。注意,我们不需要在任何地方存储中间值。

import { compose } from 'lodash/fp'

const slugify = compose(
  encodeURIComponent,
  join('-'),
  map(toLowerCase),
  split(' ')
)

slufigy('Hello World') // hello-world
转播转播
回复

使用道具

成为第一个评论人

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于作者

damonare

网站编辑

  • 主题

    267

  • 帖子

    269

  • 关注者

    0

手机版|ObjectX 超对象 |粤ICP备20005929号
Powered by  © 2019-2020版权归ObjectX 超对象