JavaScript纯函数
函数式编程中有一个非常重要的概念叫纯函数,JavaScript符合函数式编程的范式,所以也有纯函数的概念;
- 在react开发中纯函数是被多次提及的;
- React中就要求我们无论是函数还是class声明一个组件,这个组件都必须像纯函数一样(为什么是像,因为还有class组件),保护它们的props不被修改;redux中有一个reducer的概念,也是要求必须是一个纯函数;
纯函数的维基百科定义:
- 在程序设计中,若一个函数符合以下条件,那么这个函数被称为纯函数:
- 此函数在相同的输入值时,需产生相同的输出。
- 函数的输出和输入值以外的其他隐藏信息或状态无关,也和由I/O设备产生的外部输出无关。
- 该函数不能有语义上可观察的函数副作用,诸如“触发事件”,使输出设备输出,或更改输出值以外物件的内容等。
总结:
- 确定的输入,一定会产生确定的输出;
- 函数在执行过程中,不能产生副作用;
副作用:
表示在执行一个函数时,除了返回函数值之外,还对调用函数产生了附加的影响,比如修改了全局变量,修改参数或者改变外部的存储(localStorage.setItem()) ;
纯函数案例:
var names = ["abc", "cba", "nba", "dna"]
// slice只要给它传入一个start/end, 那么对于同一个数组来说, 它会给我们返回确定的值
// slice函数本身它是不会修改原来的数组
// slice -> this
// slice函数本身就是一个纯函数
var newNames1 = names.slice(0, 3)
console.log(newNames1) // ["abc", "cba", "nba"]
console.log(names) // ["abc", "cba", "nba", "dna"]
// ["abc", "cba", "nba", "dna"]
// splice在执行时, 有修改掉调用的数组对象本身, 修改的这个操作就是产生的副作用
// splice不是一个纯函数
var newNames2 = names.splice(2)
console.log(newNames2) // ["nba", "dna"]
console.log(names) // ["abc", "cba"]
练习:
// foo函数是否是一个纯函数?
// 1.相同的输入一定产生相同的输出
// 2.在执行的过程中不会产生任何的副作用
function foo(num1, num2) {
return num1 * 2 + num2 * num2
}
// bar不是一个纯函数, 因为它修改了外界的变量
var name = "abc"
function bar() {
console.log("bar其他的代码执行")
name = "cba"
}
bar()
console.log(name)
// baz也不是一个纯函数, 因为我们修改了传入的参数
function baz(info) {
info.age = 100
}
var obj = {name: "why", age: 18}
baz(obj)
console.log(obj)
// test是否是一个纯函数? 是一个纯函数
function test(info) {
return {
...info,
age: 100
}
}
test(obj)
纯函数优势:
- 可以安心的编写和安心的使用,只需要关心函数的参数和返回值;
- 你在写的时候保证了函数的纯度,只是单纯实现自己的业务逻辑即可,不需要关心传入的内容是如何获得的或者依赖其他的外部变量是否已经发生了修改;
- 你在用的时候,你确定你的输入内容不会被任意篡改,并且自己确定的输入,一定会有确定的输出;