闭包如何从之前的调用中捕获值?

How do closures capture values from previous calls?

typealias IntMaker = (Void)->Int

func makeCounter() ->IntMaker{
    var n = 0 // Line A

    func adder()->Integer{
        n = n + 1
        return n 
    }
    return adder
}

let counter1 = makeCounter()

counter1() // returns 1
counter1() // returns 2
counter1() // returns 3

不是每次调用counter1()时都会调用'Line A'吗?意思是 var n = 0 应该每次都被调用...

为什么计数器 returns 的值不同?他们不应该总是返回“1”吗?

显然,A 行 不是 每次调用 counter1 时都被调用。

事件的顺序是:

  • makeCounter 被调用,它声明并初始化 n(A 行),定义 adder 和 returns adder 在包含 n 的上下文中已经定义并初始化为 1

  • 正是这个刚刚返回的函数赋值给了counter1。因为 A 行不是该函数的一部分 (adder/counter1),所以在调用该函数时不会执行它。

  • counter1 的每次调用都在相同的上下文中执行,这就是为什么 n 在调用中保留其值的原因:它们都访问相同的 n .

您打过 makeCounter() 一次电话。这将创建您的新闭包,并将其分配给 counter1。此闭包关闭可变 var n,只要此闭包存在,就会保持捕获状态。

调用 counter1() 将执行它,但它会保留捕获的相同 n,并对其进行变异。这个特定的 "adder" 将始终捕获相同的 n,只要它存在..

要获得您建议的行为,您需要创建新的闭包来捕获 n:

的新实例
let counter1 = makeCounter()

counter1() // returns 1
counter1() // returns 2
counter1() // returns 3

var counter2 = makeCounter()
counter2() // returns 1
counter2 = makeCounter()
counter2() // returns 1
counter2 = makeCounter()
counter2() // returns 1

现在 counter1counter2 都有各自独立的 n 实例。