2

考虑以下一段 JavaScript:

<script>
function Ninja() {
   var feints = 0;
    this.getFeints = function() {
        return feints;
    }

    this.feint = function() {
        feints++;
    }

    this.increaseByTwo = function() {
        feints = feints + 2;
    } 
}

var ninja = new Ninja();
ninja.feint();

console.log(ninja.getFeints());  //outputs one
ninja.increaseByTwo();
console.log(ninja.getFeints());  // outputs three
</script>

我说上面的代码创建了四个闭包是对的吗

  • 一个忍者 - 这有点无关紧要。
  • Ninja 内部的每个内部功能都有一个。这三个闭包中的每一个都指向同一件事。

还是 JavaScript 创建了两个闭包

  • 忍者的一个 - 这有点无关紧要
  • 一为三内功。三个内部函数共享同一个闭包。
4

3 回答 3

2

所有三个内部函数都有一个指向相同环境的闭包,因此内部的变量也是如此。这通常是关闭的重点

在计算机科学中,闭包(也称为词法闭包或函数闭包)是函数或对函数的引用以及引用环境——存储对该函数的每个非局部变量(也称为自由变量)的引用的表. 1 闭包——与普通函数指针不同——允许函数访问那些非局部变量,即使在其直接词法范围之外调用也是如此。

请注意,这是内存泄漏的常见来源,因为您并不总是知道您保留了这些引用。

查看Google 的 Javascript 样式指南中关于闭包的内容

但是,要记住的一件事是,闭包会保留指向其封闭范围的指针。因此,将闭包附加到 DOM 元素会创建循环引用,从而导致内存泄漏。

于 2012-10-15T16:16:13.670 回答
1

只是,

Ninja 内部的每个内部函数都有一个

如果您要创建大量Ninjas ,那么使用Ninja's进行扩展是明智的prototype

所以,做:

var Ninja = (function () {
    function Ninja(){
        this.feints = 0;
    };

    Ninja.prototype.getFeints = function() {
        return this.feints;
    }

    Ninja.prototype.feint = function() {
        this.feints++;
    }

    Ninja.prototype.increaseByTwo = function() {
        this.feints = this.feints + 2;
    }

    return Ninja;
})();

http://jsfiddle.net/ZM3tH/

于 2012-10-15T16:15:53.333 回答
0

当您执行该代码时会发生什么?让我们逐步完成它:

  1. 您声明Ninja构造函数。在全局变量范围内。
  2. 你调用Ninja构造函数
    1. 这会创建一个新的变量环境(包含feints),它位于声明的全局范围内Ninja
    2. 创建了三个匿名函数,指向该变量环境。
    3. 一些分配完成并返回对象。
  3. 垃圾收集器检查它是否可以收集 Ninja 的变量环境: 不能,因为仍然有三个可用且可访问的函数使用它。
  4. 您在ninja. 对于每一个,
    1. 创建了一个新的空变量环境,该环境位于声明函数的范围内
    2. 该函数做了一些事情,之后本地环境被垃圾收集。

那么什么是闭包?在我的理解中,私有变量环境比Ninja()函数调用的寿命更长。因此,您的代码只创建一个闭包。

另请参阅@dystroy 的回答,它提供了有用的信息。如果我在某处使用了技术上不正确的术语,我很抱歉。Afaik,EcmaScript 规范将我所说的执行上下文和范围称为词法环境的“变量环境” ——参见第 10 节

于 2012-10-15T16:44:19.547 回答