4

我刚刚开始学习 JS 中的闭包,有人告诉我,我实际上已经编写了闭包,但没有意识到它们是闭包。我认为这只是一个单例对象/类,但他认为这是一个闭包:

var myWidget = {
    counter : 0,
    init : function() {
        myWidget.left();
        myWidget.right();
    },
    left : function() {
        // whatever
    },
    right : function() {
        // whatever
    }
}
myWidget.init();

这是闭包吗?如果不是,那是什么?

4

4 回答 4

3

是的,确实如此。

在该代码示例中,您是:

  1. 定义一个带有一些属性的普通对象
  2. 在其中一个属性(函数)中使用闭包来引用您刚刚定义的对象。

我可以看到,无论您是var myWidget在全局范围内还是在另一个函数内定义,您仍将遍历范围链以获取对myWidget.

如果我们在这里使用这个闭包定义

A closure is a combination of a code block and data of 
a context in which this code block is created.

或者Mozilla 定义

Closures are functions that refer to independent (free) variables. In other words, 
the function defined in the closure 'remembers' the environment in which it was created.

在内部执行代码块时,myWidget.init()您使用闭包myWidget在调用中引用myWidget.left()并在上下文/环境中myWidget.right()携带myWidget变量(而不是在init()函数中本地查找它)。

换句话说,当您执行myWidget.init()以下操作时:

  1. myWidget当前内部的局部变量function()吗?
  2. 向上移动到父范围(即 GLOBAL)
  3. myWidget当前(即全球)范围内的变量吗?是 --> 关闭用法
  4. 好的,使用此myWidget引用来检索变量。

我从来没有想过全局范围内的闭包,但是范围链一直传播到 GLOBAL 是完全有道理的,它只是作为另一个function() {}代码块来包装所有内容,并且是找到我们的变量的最终来源之后,这里有另一篇支持这种观点的文章:

http://lostechies.com/derickbailey/2011/11/30/is-javascripts-global-scope-really-just-a-closure/

于 2013-05-08T06:06:39.593 回答
2

对我来说,它看起来不像是关闭。这将是一个更好的例子。

function init() {
    var counter = 0;

    return {
        inc: function() {
            counter++;
        },
        show: function() {
            return counter;
        }
    }
}

counter闭包在这里的变量周围。原因是当你说

var thing = init();

Javascript 必须保留对通常是init函数的局部变量的引用,因此在执行后会被销毁。使用此设置,可以操作该局部变量的函数已返回。

试着打电话

thing.inc();
alert(thing.show());
thing.inc();
alert(thing.show());

您将在警报中看到 1 和 2,但请记住,这是您正在操作的局部变量init!那是一个关闭。

编辑

阅读了一下,很明显有问题的代码确实有一个闭包。我最喜欢这个主题的线程在这里。事实证明,我的回答是一个特定的闭包示例,但绝不是唯一一个。

于 2013-05-08T05:50:13.567 回答
0

在这种情况下不会创建闭包。请参阅此JavaScript 闭包如何工作?

访问直接词法范围之外的变量会创建一个闭包

myWidget 是在全局范围内定义的,所以 init 在访问 myWidget 时不会为它生成闭包。

如果您在函数内部定义了 myWidget,并且在 init 中访问了外部函数范围内的变量,那么将生成一个闭包。

var myWidget = (function() {
  var number = 1;

  return {
    counter : 0,
    init : function() {
      myWidget.left();
      myWidget.right();
      number++;
    },
    left : function() {
        // whatever
    },
    right : function() {
        // whatever
    }
  }
})();

myWidget.init();

当您使用上面的代码调用 init 时,会创建一个包含变量 number 的闭包

于 2013-05-08T05:55:39.280 回答
-3
For implementing javascript closure you have to get plugin that will take care of all closure properties like css closure and javascript closure.

and you have to implement closure like the following example 

<g:compress>
  <link rel="stylesheet" type="text/css" href="css/dp.css"/>
  <link rel="stylesheet" type="text/css" href="css/demo.css"/>    
</g:compress>
...
<div id="datepicker"></div>
<g:compress>
  <script type="text/javascript" src="common.js"/>
  <script type="text/javascript" src="closure/goog/base.js"/>
  <script>
       goog.require('goog.dom');
       goog.require('goog.date');
       goog.require('goog.ui.DatePicker');
  </script>
  <script type="text/javascript">
      var dp = new goog.ui.DatePicker();
      dp.render(document.getElementById('datepicker'));
  </script>
</g:compress>
于 2013-05-08T05:53:10.773 回答