【问题标题】:simple closure vs closure with nested function return简单闭包 vs 带有嵌套函数返回的闭包
【发布时间】:2016-01-05 15:50:27
【问题描述】:
var names = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight"];
var digit_name = function(n){ 
                    return names[n];
                 }
//Execute

digit_name(0)

对比

 var digit_name = (function() {
    var names = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight"];
    return function(n) {
        return names[n];
    }
})();

然后像这样执行它:

digit_name(2)

我知道这两个都是闭包,但我也认为两者的设置方式之间存在一些根本差异。有人能指出这两种设置有何不同(特别是考虑到两者都完成了相同的工作)?将全局变量附加到“窗口”与嵌套函数以模拟私有变量是我能想到的..

编辑 - 我现在很困惑是否将第一个设置视为闭包...使用 chrome,我研究了这两个设置..

var digit_name = (function() {
    var names = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight"];
    return function(n) {
        return names[n];
    }
})();
undefined
console.dir(digit_name)
function anonymous(n)
 arguments: null
 caller: null
 length: 1
 name: ""prototype: Object
 __proto__: function()
 <function scope>
     Closure names: Array[9]
     With Block: CommandLineAPI
     Global: Window

但是对于chrome中的第一个函数,

var names = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight"];
var digit_name = function(n){ 
                    return names[n];
                 }
undefined
console.dir(digit_name)
function digit_name(n)
arguments: null
caller: null
length: 1
name: ""
prototype: digit_name
__proto__: function()
<function scope>
     With Block: CommandLineAPI
     Global: Window

您可以看到 Chrome 明确表示第一次设置存在关闭,但第二次设置不存在..

【问题讨论】:

  • 只有第二个是闭包
  • @NinaScholz:如果一个闭包被定义为一个对其封闭变量范围具有永久引用的函数,那么 JS 中的每个函数都是一个闭包,无论它是否被利用。
  • @SariksaThapa:您已经描述了问题的主要区别。
  • @NinaScholz:第一个示例中的函数仍然绑定到其封闭的执行环境,即全局环境。全球环境是唯一不受任何事物约束的环境。
  • 不要过分依赖控制台输出来解释语言的含义。控制台仅显示其开发人员决定应显示的内容。他们可能只是将其关闭,因为它已经由 Global 表示。我已经远远超出了您的问题,但是您已经触及了两个原始代码示例之间的主要区别。 names 的可访问性是唯一的实际区别。

标签: javascript jquery closures


【解决方案1】:

我知道这两个都是闭包

正确。

但我也认为两者的设置方式存在一些根本差异。

错了。

这个:

var names = ["zero", "one", "two"]; // outer scope variable
var digit_name = function (n) {                        // closure -------+
    return names[n]; // outer scope variable reference                   |
}                                                      // ---------------+

还有这个

var digit_name = (function() {                        // closure --------+
    var names = ["zero", "one", "two"]; // outer scope variable          |
    return function(n) {                                 // closure ---+ |
        return names[n];  // outer scope variable reference            | |
    }                                                    // -----------+ |
})();                                                 // ----------------+

在功能上完全一样,唯一真正的区别是闭包的数量。

JavaScript 中的每个function 都会创建一个闭包,就这么简单。

不要让设置闭包的不同方式(函数语句、函数表达式或立即执行的函数表达式)让您感到困惑,最终它们都等同于同一件事。

【讨论】:

  • 但是当每个函数都是一个闭包时,为什么需要和采用闭包这个术语呢?
  • 因为“闭包”是一个关于作用域处理的概念。它定义了语义,恰好与 Javascript 函数关键字相吻合。
【解决方案2】:

首先让我们用简单的语言理解什么是闭包。

闭包是一个内部函数,它可以访问外部变量 函数(包装函数)。

现在闭包函数具有访问具有三种不同作用域的变量的神奇力量。

  1. 本地范围的变量。
  2. 它的外部函数范围的变量。
  3. 全局范围的变量。

现在,如果我们看看你描述的两种情况。

第一:

var names = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight"];
var digit_name = function(n){ 
                    return names[n];
                 }
//Execute

digit_name(0)

这里的变量namesdigit_name 具有全局范围,因为它是直接声明的,在浏览器的情况下是window(即您可以使用window.names 访问它)。现在digit_name 中存储的函数显然正在访问一个全局变量。

所以这里closure 没有图片。 (这是一个简单的函数访问全局变量的例子。

第二:

 var digit_name = (function() {
    var names = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight"];
    return function(n) {
        return names[n];
    }
})();

这里digit_name 具有全局作用域,存储在digit_name 中的函数是closure,因为它被包裹在一个外部函数(anonymous) 中,该函数在声明后立即被调用。 现在变量names 具有局部范围,因为它是在函数内部声明的,而closure 函数正在访问该函数的局部变量,因为它属于外部(包装)函数的范围。

这是一个闭包函数的例子。

希望这能帮助你理解closure

有关更多信息,您可以查看更多示例here

要了解范围,您可以参考this 答案

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-25
    相关资源
    最近更新 更多