【问题标题】:Javascript closure overwrite function expressionJavascript 闭包覆盖函数表达式
【发布时间】:2013-12-14 18:26:30
【问题描述】:

我试图弄清楚闭包是如何工作的,这是我的例子

function func1(func) {
    return function(summand) {
        return func() + summand;
    }
}

var func2 = function() {
    return 3;
}

var func3 = func1(func2);
var value = func3(4);

alert(value);

var func2 = function() {
    return 100;
}

var newValue = func3(100);
alert(newValue);

首先让我们分解代码。我编写了一个函数,它期望作为函数的参数,它会返回一个函数。

function func1(func) {
    return function(summand) {
        return func() + summand;
    }
}

然后我以表达式的形式定义了参数函数func2

var func2 = function() {
    return 3;
}

然后调用 func1 并将 func2 作为参数。结果我得到了一个函数

var func3 = func1(func2);

然后我执行函数并将 4 作为参数参数传递

var value = func3(4);

结果我得到了 7。然后我覆盖 func2 并返回 100

var func2 = function() {
    return 100;
}

然后再次调用func3并作为参数值100传递。

var newValue = func3(100);

结果我得到了 103。我定义的第一个函数(返回一个函数并将函数作为参数)仍将使用 func2 的第一个版本。这就是关闭的力量,我知道。
但是看看下面的代码,当我将 func2 定义为函数声明而不是表达式时,那么 func2 将覆盖

function func1(func) {
    return function(summand) {
        return func() + summand;
    }
}

function func2() {
    return 3;
}

var func3 = func1(func2);
var value = func3(4);

alert(value);

function func2() {
    return 100;
}

var newValue = func3(100);
alert(newValue);

第一个值为 104,第二个值为 200。
我的问题是,为什么当我使用函数声明时它会覆盖旧函数,在这个例子中是 func2。但是当我使用函数表达式时,它将保留对旧 func2 的引用。
是因为函数提升?

【问题讨论】:

标签: javascript closures


【解决方案1】:

当您使用function foo() { ... } 样式时,您正在定义一个名称为foo 的函数。当您使用var foo = function() { ... } 样式时,您声明了一个变量foo(将被提升),并将匿名函数作为其值分配给它。

可以写

var a;
a = 2;
// ...stuff...
a = 3;

我们期望值是 3。所以它在这里,提升使这个像:

var func2;
func2 = function() { .. some stuff.. };
// ...stuff...
func2 = function() { .. some other stuff .. };

相比之下,我认为如果你定义函数,它只会在初始解析中采用一个或其他函数定义。

【讨论】:

    【解决方案2】:

    因为吊装。使用function statement 而不是function expression 会导致函数func2 被提升到作用域的顶部。在执行范围内的任何代码之前,您将覆盖 func2

    因为提升你的代码实际上看起来像这样:

    function func1(func) {
        return function(summand) {
            return func() + summand;
        }
    }
    
    function func2() {
        return 3;
    }
    
    // Hoisted!!! Overwriting the previous func2 definition.
    function func2() {
        return 100;
    }
    
    var func3 = func1(func2);
    var value = func3(4);
    
    alert(value);
    
    var newValue = func3(100);
    alert(newValue);
    

    func1 内部,func 是对其传递的函数的稳定引用……只是你在传递之前传递了return 100; 版本。

    【讨论】:

    • function 不是运算符。
    • 谢谢!在 MDN 中修复。稍后将移出 /operators/。
    【解决方案3】:

    这不是因为闭包。

    就像你想的那样 - 这个问题是由于函数提升

    您可以将函数声明视为“上移”到当前作用域的开头。

    var f2 = function(){
        return 50;
    }
    function f2(){
        return 100;
    }
    

    在这种情况下,f2 为 50,因为它的解析方式类似于:

    var f2 = function(){
        return 100;
    }
    var f2 = function(){
        return 50;
    }
    

    因为吊装。

    【讨论】:

      猜你喜欢
      • 2016-12-05
      • 1970-01-01
      • 2010-10-30
      • 1970-01-01
      • 2013-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-09
      相关资源
      最近更新 更多