JavaScript 函数式编程

简述

如果你没接触过函数式编程,那么希望这篇文章能帮助到你。如果你也恰好使用的是javascript,那么就再好不过啦~

  1. 本文首先介绍函数式编程的定义及其核心的概念:λ演算;

  2. 接下来结合函数式编程的特点来帮助理解λ演算,发现其中一以贯之的原理;

  3. 再结合函数式编程常用的工具,加深对上面所述的数式编程的特点的理解;

  4. 最后用两个在平常就可能接触过的例子来打破函数式编程的壁垒,望君在本文大量文字的背后能把握最核心的东西。

1.定义

函数式编程(英语:functional programming)或称函数程序设计、泛函编程,是一种编程范式,它将计算机运算视为函数运算,并且避免使用程序状态以及易变对象。其中,λ演算(lambda calculus)为该语言最重要的基础。而且,λ演算的函数可以接受函数当作输入(引数)和输出(传出值)。

----维基百科

所以,接下来我们来了解下什么是λ演算

λ演算

λ运算的核心是λ表达式,以此形成函数定义函数应用递归的形式系统。当使用λ表达式定义出布尔值、数值和各种基本操作符等语言元素后,就能够形成一种编程语言,所以,λ运算是函数式编程语言共同的祖先.

由于任何一个可计算函数都能用λ运算来表达和求值,因而它等价于图灵机(图灵完备)。

λ表达式(也可以称之为项:λ-expression or λ-term)有且仅有以下三种合法形式:

1.变量(Variable)

形式 x

描述:变量名可能是一个字符或字符串,它表示一个参数(形参)或者一个值(实参)。

e.g.bar x y z

2.抽象(Abstraction)

形式λx.M

描述:它表示获取一个参数x并返回M的lambda函数,M是一个合法lambda表达式,且符号λ和.表示绑定变量x于该函数抽象的函数体M。简单来说就是表示一个形参为x的函数M。

e.g.λx.y λx.(λy.xy),其中:

λx.y表示一个常量函数(constant function),输出恒为y与输入无关

λx.(λy.xy)的输出是一个函数抽象λy.xy,输入可以是任意的lambda表达式。

注意:一个lambda函数的输入和输出也可以是函数。
3.应用(Application)

形式M N

描述:它表示将函数M应用于参数N,其中MN均为合法lambda表达式。简单来说就是给函数M输入实参N

e.g.(λx.x) y, (λx.x) (λx.x),其中:

(λx.x) y表示将函数λx.x应用于变量y,得到y;

(λx.x) (λx.x)表示将函数λx.x应用于λx.x,得到λx.x。函数λx.x是一个恒等函数(identity function),即输入恒等于输出,它可以用 I 来表示.

λ表达式是函数式编程的数学基础,也是函数式编程的思想核心。函数式编程所具有的的特点也来源自λ表达式。

2.特点

函数式编程作为一种编程范式,自然会有自己独特之处。本节将列举这些特点,并举例说明与我们平常coding时的不同之处。

2.1 一等公民的函数

当我们说函数是“一等公民”的时候,我们实际上说的是它们和其他对象都一样…

所以就是普通公民。函数真没什么特殊的,你可以像对待任何其他数据类型一样对待它们——把它们存在数组里,当作参数传递,赋值给变量…等等。

函数对应了λ表达式中的抽象,在λ表达式的定义中,抽象与变量平起平坐,并无差异。

虽说在JavaScript语言中,这是基本概念,但在实际应用中仍有如下不合理的代码组织存在:

// 太傻了
const getServerStuff = callback => ajaxCall(json => callback(json));

// 这才像样(其效果跟上面是等价的)
const getServerStuff = ajaxCall;

下面是这样做的原因

  • 这样做除了徒增代码量,提高维护和检索代码的成本外,没有任何用处。

  • 如果一个函数被不必要地包裹起来了,而且发生了改动,那么包裹它的那个函数也要做相应的变更。

2.2 纯函数

纯函数是这样一种函数,即相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用。

即:相同输入得到相同输出

举个例子:

// 不纯的
var minimum = 21;

var checkAge = function(age) {
   
  return age >= minimum;
};


// 纯的
var checkAge = function(age) {
   
  var minimum = 21;
  return age >= minimum;
};

副作用是在计算结果的过程中,系统状态的一种变化,或者与外部世界进行的可观察的交互。

副作用可能包含,但不限于:

  • 更改文件系统
  • 往数据库插入记录
  • 发送一个 http 请求
  • 可变数据
  • 打印/log
  • 获取用户输入
  • DOM 查询
  • 访问系统状态

这个列表还可以继续写下去。概括来讲,只要是跟函数外部环境发生的交互就都是副作用——这一点可能会让你怀疑无副作用编程的可行性。函数式编程的哲学就是假定副作用是造成不正当行为的主要原因。

纯函数的优势

  1. 可缓存性(Cacheable)

纯函数总能够根据输入来做缓存,实现缓存的一种典型方式是 memoize 技术:

var squareNumber  = memoize(function(x){
    return x*x; });

squareNumber(4);
//=> 16</
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值