【问题标题】:Calling correctly a closure with a return正确调用带有返回的闭包
【发布时间】:2015-02-16 16:32:01
【问题描述】:

这很好用:

var test = function(){
    var a = 0;
    console.log(a);
    return function (){
        a++;
        return a;    
    };
};

var counter = test();

console.log(counter()); //1
console.log(counter()); //2
console.log(counter()); //3
console.log(counter()); //4

为什么我不能得到相同的结果:

console.log(test());

以及为什么我需要在这里通过一个有些冗余的代理(var counter)工作,前提是以下工作正常):

var test = function(k,l){
    var c = k + l;
    return c;
};

console.log(test(1,2));

这是否与存在闭包的事实有关,我正在调用一个函数,该函数返回一个函数,该函数最终返回一些值?我真的需要在这里定义一个新变量吗,或者我可以节省时间和代码行并直接让它工作?

【问题讨论】:

    标签: javascript closures return-value


    【解决方案1】:

    这是否与存在闭包的事实有关,我正在调用一个函数,该函数返回一个函数,该函数最终返回一些值?

    是的。你的函数test() 除了设置一个变量,记录0,然后返回另一个(运算符)函数,它在test() 的范围内关闭。

    我真的需要在这里定义一个新变量,或者我可以节省时间和代码行并直接让它工作吗?

    再次是的。您需要通过test() 持有对该返回函数的引用,该函数具有一个活动的作用域链条目。如果没有任何活动引用(例如将其分配给变量),垃圾收集器会清理它。

    【讨论】:

    • 这是一个很好的解释。所以,无论如何,在我的第一种情况下,我最终会得到一个全局变量 counter,甚至考虑避免全局变量?
    • 你的变量是否是全局的,取决于你和你的代码。例如,您始终可以使用 (function() {}()); 封装您的代码以创建自己的应用程序范围,这是常见的做法。
    • 谢谢,我听说过这种方法,我认为它与封装的概念密切相关。另一方面,您可能知道为什么通过运行 console.log(test()); 直接调用函数而不使用代理变量(让我们暂时将存储递增值的目的放在一边);产生一个非常奇怪的结果:0 function (){ a++; return a; }。它会记录0,但也会记录嵌套函数,而不是执行它并返回结果?
    【解决方案2】:

    这取决于你想做什么。

    您的第一个示例是一个保存状态的计数器(记住最后一个值)。你可以有多个计数器来计算不同的东西。

    第二个例子是一个函数,它只是将数字相加,但下次不保持状态或做任何不同的事情。

    如果您想拥有一个计数器但不必先创建它,您可以这样做:

    var total = 0;
    
    function count(){
        total = total + 1;
        return total;
    }
    

    那么现在:

    console.log(count()); // 1
    console.log(count()); // 2
    console.log(count()); // 3
    

    或者在函数中隐藏变量:

    function counter(){
        counter.total = (counter.total||0) + 1;
        return counter.total;
    }
    

    然后:

    console.log(counter()); // 1
    console.log(counter()); // 2
    console.log(counter()); // 3
    

    【讨论】:

    • 我想避免使用全局变量,但我想我不能,因为解释器不会存储 a 的值,并且会在函数执行后直接丢弃它。我希望我在嵌套(我喜欢称其为子)函数中引用此变量 a 的事实会有所帮助,并且不会被丢弃。
    • @Vadimster,如果你想避免全局,那么我认为你的关闭方法是最好的。这样做有什么问题?
    • @ChrisC 我仍然需要创建一个全局变量var counter = test();,因为如果我理解正确,垃圾收集器将不会存储我的var a,因为它在外部没有任何有用的链接,并且只是函数中的局部变量。但是一旦我创建了一个引用,我想它就不会被触及。
    • @Vadimster,好的,我明白了。如果你需要你的计数器函数是全局的,但又不想有一个单独的变量,那么你可以将它与函数一起存储。我将进行编辑以显示此内容。
    猜你喜欢
    • 2021-02-04
    • 2017-04-17
    • 1970-01-01
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    相关资源
    最近更新 更多