3

我了解到纯函数是一个不会改变全局状态的函数。如果这是真的,函数内的函数可以改变外部函数的状态并且仍然是纯的,对吗?

例子:

function func1() {
  let name = "My Name"
  func2()  

  function func2() {
    // alter name here.
  }
}

在上面的例子中,func2仍然是纯的,因为它不使用任何全局状态。

这就是我的看法,但我的工作同事认为这func2并不纯粹,应该这样写:

function func1() {
  let name = "My Name"
  func2(name)  

  function func2(name) {
    // use name here.
  }
}

这很糟糕,因为:

  • 如果 v8 没有对此进行优化,CPU 将运行更多指令
  • 阴影是一种不好的做法

问题是:当我们谈论函数中的函数时,纯函数到底是什么?

4

4 回答 4

3

Purity并没有被定义为只关心全局变量,它关心任何不应该被改变的非局部变量(以及更多)。闭包的外部变量仍然算作非局部变量,它不需要是全局变量。

因此,如果func2更改name,则它是不纯的。是否func1也会因此变得不纯,这取决于您是否只考虑外部纯度——只要namefunc2保持在函数内部,它可能仍然是纯的。

于 2019-04-23T16:31:58.087 回答
2

纯函数是满足 2 个要求的函数:

  1. 给定相同的输入,它将始终返回相同的输出。
  2. 不会产生副作用。

副作用可以定义为“除返回值外,在被调用函数之外可观察到的任何应用程序状态变化”


更加具体:

  • 修改其范围之外的任何内容(即使它不是全局范围)的函数不是纯函数。

  • 在您的示例中,如果 func2 在其自身范围之外修改变量,则它不是纯函数:

function func1() {
  let name = "My Name"; // <-- the variable is not in the global scope but, in any case, it is outside the scope of func2
  func2();

  function func2() {
    // alter name here.
  }
}
于 2019-04-23T16:55:53.277 回答
1

我了解到纯函数是一个不会改变全局状态的函数。

嗯,这过于简单化了。一个纯函数应该一,没有副作用,二,它的结果应该只依赖于参数。因此,作为推论,没有状态。你func1name财产看起来像一个州。我可以变异它吗?会func1()根据先前的调用产生不同的结果吗?不纯!

当然,func2 不纯是无可争议的。您写了“更改名称”-“名称”超出了其范围。这是一个副作用。

于 2019-04-23T16:49:26.783 回答
0

另一个我认为值得一提的例子是跟随纯函数

function insert(DB, user) {
    return function() {
        throwIfUserExists(DB, user);
        var savedUser = saveUser(DB, user);
        return savedUser;
    }
}

请注意,当您调用 时insert,只要您继续发送相同的DBand user,您将收到与该函数返回另一个函数相同的输出 - 不会发生副作用。

于 2019-11-18T10:13:00.023 回答