JavaScript函数式编程之副作用

简介:

更多相关内容见博客 github.com/zhuanyongxi…

概念:

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

上文中的纯函数的概念很严格,这个副作用的概念也是。它的要求很高,概括的讲,只要是跟函数外部环境发生的交互就都是副作用。从“副作用”这个词语来看,它更多的情况在于“改变系统状态”。

教程中列举的一些副作用:

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

如果完全没有副作用,那我们的代码就是单纯的跑一遍浪费了一点电而已,除此之外什么都没有发生,这样的话我们写代码就没有意义了。所以,在JS中,我们的目的不是完全消除副作用注1,而是避免那些不应该出现的副作用。

JS原生的方法中,map就很函数式,他会返回一个新的数组,不会改变原数组。而pop这种方法就很不好,它在操作了数组之后,也改变数组本身。

所以当我们要使用那些有副作用的方法写纯函数的时候,记得做一次深拷贝:

例1


const myPop = x => {
  let [...y] = x;
  return y.pop();
}

使用一个固定的共享状态或者调用一个纯函数不算是副作用,例子如下:

例2

const a = 5;
function A(b) {
  return a + b;
}
A(5);

调用纯函数的例子:

例3


function foo(x) {
  return bar(x);
}

function bar(y) {
  return y + 1;
}

foo(1);

虽然不算是副作用,可更加推荐的方式是把函数bar用参数的方式传进来,这样就做到了解耦,用起来更加的方便:

例4


function foo(fn, x) {
  return fn(x);
}

function bar(y) {
  return y + 1;
}

foo(bar, 1);

如果使用柯里化的方式,会更加的清爽和方便:

例5


function foo(fn) {
  return function(x) {
    return fn(x);   
  }
}

function bar(y) {
  return y + 1;
}

foo(bar)(1);

这个例子依然存在一个会令我们感到不安的地方,那就是bar可能会被修改。例如:

例6


function foo(fn, x) {
  return fn(x);
}

function bar(y) {
  return y + 1;
}
bar = undefined;
foo(bar, 1);

当然我们平时很少会大脑抽筋在全局作用域下写出一个bar = undefined来让我们的系统出错,这更可能在某个有副作用的函数内出现这种情况。这就是为什么我们要避免副作用。这个情况在ES6中会得到改善,例如:

例7


const foo = function(fn, x) {
  return fn(x);
}

const bar = function(y) {
  return y + 1;
}
bar = undefined;	// error
foo(bar, 1);

个人建议用const的方式,这样更加的安全,即便出错也可以快速定位。

注释:

  • 注1: 如果继续深入学习,对与上面列出的一些副作用,函数式还有一种延迟执行的方式(IO容器)来使这些操作变纯。

参考资料:



原文发布时间为:2018年06月14日
原文作者:砖用冰西瓜
本文来源:  掘金  如需转载请联系原作者



相关文章
|
11月前
|
前端开发 JavaScript 数据处理
深入学习JavaScript ES8函数式编程:特性与实践指南
深入学习JavaScript ES8函数式编程:特性与实践指南
77 0
|
3月前
|
存储 JavaScript 前端开发
JavaScript——函数式编程Functor(函子)
JavaScript——函数式编程Functor(函子)
24 0
|
5月前
|
前端开发 JavaScript 开发者
函数式编程在JavaScript中的应用
【6月更文挑战第10天】本文探讨了函数式编程在JavaScript中的应用,介绍了函数式编程的基本概念,如纯函数和不可变数据。文中通过示例展示了高阶函数、不可变数据的使用,以及如何编写纯函数。此外,还讨论了函数组合和柯里化技术,它们能提升代码的灵活性和可重用性。掌握这些函数式编程技术能帮助开发者编写更简洁、可预测的JavaScript代码。
|
6月前
|
JavaScript 前端开发
JavaScript 的数组方法 map()、filter() 和 reduce() 提供了函数式编程处理元素的方式
【5月更文挑战第11天】JavaScript 的数组方法 map()、filter() 和 reduce() 提供了函数式编程处理元素的方式。map() 用于创建新数组,其中元素是原数组元素经过指定函数转换后的结果;filter() 则筛选出通过特定条件的元素生成新数组;reduce() 将数组元素累计为单一值。这三个方法使代码更简洁易读,例如:map() 可用于数组元素乘以 2,filter() 用于选取偶数,reduce() 计算数组元素之和。
46 2
|
6月前
|
JavaScript 前端开发 测试技术
JavaScript中的函数式编程:纯函数与高阶函数的概念解析
【4月更文挑战第22天】了解JavaScript中的函数式编程,关键在于纯函数和高阶函数。纯函数有确定输出和无副作用,利于预测、测试和维护。例如,`add(a, b)`函数即为纯函数。高阶函数接受或返回函数,用于抽象、复用和组合,如`map`、`filter`。函数式编程能提升代码可读性、可维护性和测试性,帮助构建高效应用。
|
6月前
|
JavaScript 前端开发 索引
JavaScript函数式编程【进阶】
JavaScript函数式编程【进阶】
54 1
|
6月前
|
存储 JavaScript 前端开发
JavaScript函数式编程[入门]
JavaScript函数式编程[入门]
53 1
|
6月前
|
前端开发 JavaScript 数据处理
深入学习JavaScript ES8函数式编程:特性与实践指南
深入学习JavaScript ES8函数式编程:特性与实践指南
115 0
|
缓存 JavaScript 前端开发
带你读《现代Javascript高级教程》十四、JavaScript函数式编程(1)
带你读《现代Javascript高级教程》十四、JavaScript函数式编程(1)
|
JavaScript 前端开发 测试技术
带你读《现代Javascript高级教程》十四、JavaScript函数式编程(2)
带你读《现代Javascript高级教程》十四、JavaScript函数式编程(2)