【问题标题】:Difficulty understanding closure example难以理解的闭包示例
【发布时间】:2015-02-05 14:27:29
【问题描述】:

在尝试了解什么是闭包时,我在理解 Closure 维基百科文章中提供的以下示例时遇到了问题。 WikiPage。 您能否帮助我理解这一点,并在这样做时提供一个易于理解的闭包定义。

function startAt(x)
   function incrementBy(y)
       return x + y
   return incrementBy

variable closure1 = startAt(1)
variable closure2 = startAt(5)

【问题讨论】:

标签: closures


【解决方案1】:

要了解闭包,您首先需要了解作用域。范围是变量的生命周期。在作用域内声明的变量诞生了,当作用域结束时它就消失了。例如:

{              // scope begins
    var x = 0; // variable x is born
    var y = 1; // variable y is born
}              // scope ends, x and y both die

现在,有一种方法可以让变量在声明的作用域结束后仍保持活动状态。简而言之,这是一种变量可以欺骗死亡的方式。变量欺骗死亡的方式是通过闭包。

考虑另一个范围内的范围。内部范围可以访问外部范围内声明的所有变量。但是,外部作用域无法访问内部作用域内声明的任何变量。

{                  // the outer scope has access to x and y only
    var x = 0;
    var y = 1;

    {              // the inner scope has access to x, y and z
        var z = 2;
    }
}

内部作用域可以访问z,因为它是在内部作用域中声明的。但是,它也可以访问xy,因为这两个变量位于内部作用域的词法环境(即父作用域)中。

现在考虑如果我们可以将这个内部作用域移到外部作用域之外会发生什么。

{                  // the outer scope has access to x and y only
    var x = 0;
    var y = 1;

    {              // the inner scope has access to x, y and z
        var z = 2;
    } ---+
}        |
         |
{ <------+         // the inner scope moved outside of the outer scope
    var z = 2;
}

在这种情况下,外部作用域结束。因此,xy 应该随着外部作用域而死。但是,它们不能死,因为它们仍然是内部作用域所需要的。当内部作用域被移到外部作用域之外时,它成为变量xy(这是它的上值)的闭包,并且只要这些变量本身存在,它就会使这些变量保持活动状态。这就是闭包的一般概念。

现在考虑以下代码:

function startAt(x) {
    return incrementBy;

    function incrementBy(y) {
        return x + y;
    }
}

var closure1 = startAt(1);
var closure2 = startAt(5);

这里,incrementBy 函数是一个内部函数。因此,它可以访问属于startAt 函数的变量x。然而,当我们从startAt 返回incrementBy 时,我们将内部函数移到外部函数之外。因此,虽然x应该随着startAt的回归而死去,但它仍然活着,因为incrementBy需要它。

因此,incrementBy 是一个闭包,因为它关闭了变量 x 并在它自己存在的时候让它保持活动状态;而变量x被称为闭包incrementBy的上值。

【讨论】:

    猜你喜欢
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    • 2015-03-11
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多