JS 函数式编程思维简述(一):无副作用

  1. 简述
  2. 无副作用(No Side Effects)
  3. 高阶函数(High-Order Function)
  4. 柯里化(Currying)
  5. 闭包(Closure)
  6. 不可变(Immutable)
  7. 惰性计算(Lazy Evaluation)
  8. Monad

简述

       函数式编程的概念来自于数学中的函数,即自变量映射。中心思想是指:一个函数的返回值,仅仅依赖于参数的值,而不会因为其他外部的状态而不同。比如有一个求幂的函数 pow(base, exponent) ,它的计算结果仅仅依赖于 base (基数)exponent (指数) 的不同而不同。这个函数无论我们调用多少次,只要参数一致,那么返回值绝对一致。
       在代码构建的过程中,我们很难将所有函数都构建成符合函数式编程思维的范式,但如果应用函数式编程,则它的好处主要体现于:

  • 引用透明(Referential Transparency)
  • 无副作用(No Side Effect)
  • 无竞争态 (No Race Condition)
  • 惰性求值 (Lazy Evaluation)

       本文的目的是希望以简单易懂的方式,表述函数式编程思维的范式和应用。本文中示例使用的编程语言为:JavaScript

无副作用(no side effects)

       函数在表现方式上,我们可以将其区分为 纯函数非纯函数。他们有以下区分:

纯函数:返回值仅依赖于参数,输入相同的值,便会得到相同的值的函数。

let seed = 0; // 定义一个外部变量
// 一个用于求和的函数
const sum = (x, y) => x + y;

sum(10, 2); // 结果: 12
sum(10, 2); // 结果: 12
sum(3, 6); // 结果: 9
sum(3, 6); // 结果: 9
console.log( seed ); // 输出: 0

非纯函数:在参数一致的情况下,返回值可能不一致的函数。

let seed = 0; // 定义一个外部变量
// 另一个用于求和的函数
const sum = (x, y) => x + y + (++seed);

sum(10, 2); // 结果: 13
sum(10, 2); // 结果: 14
sum(3, 6); // 结果: 12
sum(3, 6); // 结果: 13
console.log( seed ); // 输出: 4

       纯函数非纯函数 最大的两个不同的表现在于:副作用性引用透明性
       副作用性 是指,该函数的调用过程中,是否对主函数(调用者)产生了附加影响,例如修改了函数外的变量或参数,我们就认为该函数是 有副作用 的函数。
       而 引用透明 则是指,函数的运行不依赖于外部的变量或者状态,仅仅依赖于输入的参数。如果程序中任意两处具有相同输入值的函数调用能够互相置换,而不影响程序的动作,那么该函数就具有引用透明性。
       由上述示例可见,非纯函数造成的最大的问题,就是其 不可预知性 。如果代码比较复杂时,会为我们梳理程序运行逻辑造成一定的困难。因此,在函数式编程思维中,我们应尽可能的确保我们编写的函数是 纯函数

JavaScript内置对象中的 非纯函数

       在理想中,我们的函数都应该是 纯函数 。但理想往往需要屈从于现实状况。在 JavaScript 的内置对象中,就有非常多的 非纯函数 ,也提供着必要的功能实现,如我们常见的:

  • Math.random()
  • console.log()
  • element.addEventListener()
  • Date.now()
  • Array.prototype.sort()
  • ajax操作等

副作用主要表现于:

  • I/O 操作:其结果本身就是无法预估的,因此无法判断给定了的参数,是否能给予我们预期的返回结果;比如接收输入、或者将结果输出。
  • 改变全局变量原有值,或者改变参数对象值及其属性:其执行结果也是带有副作用的。
  • 抛出异常或以错误中止:函数除了返回一个值之外,还可能发生不太确定的执行结果。

       Array 是一个专门用于操作数组的对象,是所有数组的父级对象,设定了所有数组可调用的方法有哪些。我们常用 slice()splice() 来作为纯函数和非纯函数的典型示例:

函数 作用
slice( [begin, end] ) 方法返回一个新的数组对象,这一对象是一个由 begin和 end(不包括end)决定的原数组的浅拷贝。原始数组不会被改变。
参数:
begin:操作起始位置索引;
end:操作结束位置索引(不包含);
splice(start[, deleteCount]) 方法通过删除现有元素和/或添加新元素来修改数组,并以数组返回原数组中被修改的内容。
参数:
start:操作起始位置索引;
deleteCount:删除元素的数量;

假设我们现在有一个数组 [1,3,5,7,9] ,当我们希望从 begin 位置开始检索,获取到 end 位置时,我们会这么去做:

const arr = [1, 3, 5, 7, 9];

// slice() 是一个纯函数!
arr.slice(1, 3); // 结果:[3, 5]
arr.slice(1, 3); // 结果:[3, 5]
arr.slice(1, 3); // 结果:[3, 5]

而假设我们要在数组 [1,3,5,7,9] 中删除相应数据时:

const arr = [1, 3, 5, 7, 9];

// splice() 不是一个纯函数!
arr.splice(1, 3); // 结果:[3, 5, 7]
arr.splice(1, 3); // 结果:[9]
arr.splice(1, 3); // 结果:[]

在一段程序中,我们无法保证所有的函数都是纯函数。但纯函数的覆盖面越大,对于调试、缓存数据及线程安全都会提供越多的便利。有一种说法是,保证80%的函数是纯函数即可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容