JavaScript封闭如何在以下示例中起作用?

时间:2016-02-16 20:35:20

标签: javascript closures

我有以下代码:

var x = 6;
var y = 4;
var a = function(b) { 
    return function(c) { 
        return y + b + c; 
    } 
};

x = 2;
y = 5;

var fn = a(x);

x = 1;
y = 3;

为了让fn(unknown)输出10,我被要求弄清楚需要什么未知:

console.log(fn(unknown)); // This should output 10

我知道未知需要为5才能使fn输出为10,但是有人可以解释为什么吗?

我确定它与机箱有关,但不太了解如何在不同阶段分配变量。

3 个答案:

答案 0 :(得分:3)

我听过的最简单的闭包描述是:

  

这是一种函数可以无限制地访问其创建环境的方法。

所以:

var a = function(b) {            /* "outer"  aka  "functionofb" */
    return function(c) {         /* "inner"  aka  "functionofc" */
        return y + b + c; 
    } 
};

我们将会看到这是如何让内部函数无限期地访问(内部)变量'b'的副本,因为它存在于内在的生命中。 (在此示例中,内部函数永远不会更改其'b'副本的值,但它可以。)

因此,为了完成您的示例,让我们从这里开始:

     x = 2;
var fn = a(x);

变量a“指向”未命名的(匿名)函数(带有'b'作为arg的那个),所以这基本上是:

fn = functionofb(x);

或:

fn = functionofb(2);

现在'functionofb'是一个返回函数的函数。它返回的函数是:

function(c) { 
    return y + b + c; 
}

(这也是匿名的,所以我们称之为`functionofc')

所以:

function(c) { 
    return y + 2 + c;       /* here 'b's value is 'captured' by the closure */
}

然后我们有:

y = 3;

并做:

fn(5);

这只是:

functionofc(5);

给了我们:

return y + 2 + c;

或者:

return 3 + 2 + 5;            /* 'y' was never captured, the current value is used */

哪个是理想的答案:

10

其他一切都只是红色的鲱鱼。

有关JavaScript 闭包的更全面讨论,请参阅How do JavaScript closures work?

答案 1 :(得分:2)

当你这样做时......

var fn = a(x);

......变量fn等于......

function(c) { 
    return y + 2 + c; 
} 

...因为此时x等于2,执行函数x时捕获(固定)a的值。

因此,当您在运行函数fn(5)的那一刻执行变量y等于3的fn时,这意味着函数将执行此操作。

return 3 + 2 + 5; 

由于3 + 2 + 5 = 10,这意味着您的输出为10.

注1:

如果您在fn(5)之前运行了

y = 3;,则会返回12,因为此时y的值为5。有关演示,请参阅this Fiddle

注2:

有关闭包的更多信息,请参阅此问题:

How do JavaScript closures work?

答案 2 :(得分:1)

您需要将5作为unknown传递。

完整性闭包的简要定义

来自This SO link

  
      
  • 闭包是函数的局部变量 - 在函数返回后保持活动状态,或
  •   
  • 一个闭包是一个堆栈框架,当函数返回时它没有被释放(好像一个'堆栈框架'是malloc'而不是在堆栈上!)。
  •   

数字是javascript中的值传递

传递给b的{​​{1}}参数保存在a()返回的闭包中。因此,在您的示例中,a被保存为bx的值。这是因为javascript中的2 s是按值传递的。这意味着更改Number不会更改x返回的闭包内b的值。

清晰的简短例子:



a




在闭包

中引用全局范围内的对象

闭包中的var a = function(x) { return function() { return x + 1; }; }; var x1 = 1; var fn1 = a(x1); // x1 is passed by value, so x inside the closure is its own copy of 1 x1 = 2 // no effect on the next line console.log(fn1()) // prints 2, does NOT print 3变量y直接从全局范围返回引用a,因此全局范围中y的更改会改变{的值y返回的闭包中的{1}}。

简洁示例:



y




全部放在一起

a是一个副本,对于整个示例保留2,var x = 1; var a = function() { return x + 1; }; console.log(a()); // prints 2, since x is still 1 x = 2; console.log(a()); // prints 3, since the a() closure references the global x引用一个全局变量,可能会在调用b后更改它的值,并y 1}}将是a()的值,因为它是c返回的闭包的参数。

完整性的例子:



unknown