• 函数的返回结果只依赖于它的参数。
    • 函数执行过程里面没有副作用。
    1. const a = 1
    2. const foo = (b) => a + b
    3. let res = foo(2)
    4. console.log(res);

    foo 函数不是一个纯函数,因为它返回的结果依赖于外部变量 a,我们在不知道 a 的值的情况下,并不能保证 foo(2) 的返回值是 3。虽然 foo 函数的代码实现并没有变化,传入的参数也没有变化,但它的返回值却是不可预料的,现在 foo(2) 是 3,可能过了一会就是 4 了,因为 a 可能发生了变化变成了 2

    1. const a = 1
    2. const foo = (x, b) => x + b
    3. foo(1, 2) // => 3

    现在 foo 的返回结果只依赖于它的参数 x 和 b,foo(1, 2) 永远是 3。今天是 3,明天也是 3,在服务器跑是 3,在客户端跑也 3,不管你外部发生了什么变化,foo(1, 2) 永远是 3。只要 foo 代码不改变,你传入的参数是确定的,那么 foo(1, 2) 的值永远是可预料的。 这就是纯函数的第一个条件:一个函数的返回结果只依赖于它的参数。

    1. const a = 1
    2. const foo = (obj, b) => {
    3. return obj.x + b
    4. }
    5. const counter = { x: 1 }
    6. foo(counter, 2) // => 3
    7. counter.x // => 1

    我们把原来的 x 换成了 obj,我现在可以往里面传一个对象进行计算,计算的过程里面并不会对传入的对象进行修改,计算前后的 counter 不会发生任何变化,计算前是 1,计算后也是 1,它现在是纯的。但是我再稍微修改一下它:

    1. const a = 1
    2. const foo = (obj, b) => {
    3. //这里修改了obj,纯函数不能修改函数参数
    4. obj.x = 2
    5. return obj.x + b
    6. }
    7. const counter = { x: 1 }
    8. foo(counter, 2) // => 4
    9. counter.x // => 2

    现在情况发生了变化,我在 foo 内部加了一句 obj.x = 2,计算前 counter.x 是 1,但是计算以后 counter.x 是 2。foo 函数的执行对外部的 counter 产生了影响,它产生了副作用,因为它修改了外部传进来的对象,现在它是不纯的。

    1. 但是你在函数内部构建的变量,然后进行数据的修改不是副作用:
    2. const foo = (b) => {
    3. const obj = { x: 1 }
    4. obj.x = 2
    5. return obj.x + b
    6. }
    7. 这里在函数内部申明的对象,因此在函数内部修改的对象,而不是因为外部因素产生的副作用,因此这个函数是一个纯函数