'关闭的定义'

时间:2015-06-26 22:47:50

标签: javascript closures

让我问一个问题。它是关于JavaScript中的闭包,而不是关于它们是如何工作的。

David Flanagan在他的#4; JavaScript The Definitive Guide 6th Edition"写道:

... 从技术上讲,所有JavaScript函数都是闭包:它们是对象,并且它们具有与之关联的作用域链。 ...

这是对的吗?我可以调用每个函数(函数对象+它的范围)a"关闭"?

并堆叠'标签"关闭"表示:

闭包是一个第一类函数,它引用(关闭)变量来自定义它的作用域。 如果闭包仍然存在在其定义范围结束后,它关闭的变量也将继续存在。

在JavaScript中,每个函数都引用来自定义范围的变量。所以,它仍然有效。

问题是: 为什么许多开发者会这样想?这个理论有问题吗?它不能用作一般定义吗?

4 个答案:

答案 0 :(得分:2)

从技术上讲,所有功能都是闭包。但是如果函数没有引用任何自由变量,则闭包的环境是空的。只有当需要与函数代码一起保存的闭合变量时,函数和闭包之间的区别才有意义。因此,将不能访问任何自由变量的函数称为函数,以及那些作为闭包的函数,这是很常见的,这样您就知道了这种区别。

答案 1 :(得分:1)

这是一个棘手的术语。简单地声明的功能只是一个功能。什么使闭包是调用函数。通过调用一个函数,可以为传递的参数和声明的局部变量分配空间。

如果一个函数只是返回一些值,并且该值只是简单的东西(比如,什么都没有,或者只是一个数字或一个字符串),那么关闭就会消失,对它来说真的没什么好玩的。但是,如果某些引用参数或局部变量(大多数都是相同的)"转义"函数,然后是闭包 - 为局部变量分配的空间,以及父空间链 - 坚持下去。

这是一些参考文献可以“逃避”的方式。来自一个功能:

function escape(x, y) {
  return {
    x: x,
    y: y,
    sum: function() { return x + y; }
  };
}

var foo = escape(10, 20);
alert(foo.sum()); // 30

该对象从函数返回并保存在" foo"将保持对这两个参数的引用。这是一个更有趣的例子:

function counter(start, increment) {
  var current = start;
  return function() {
    var returnValue = current;
    current += increment;
    return returnValue;
  };
}

var evenNumbers = counter(0, 2);
alert(evenNumbers()); // 0
alert(evenNumbers()); // 2
alert(evenNumbers()); // 4

在那一个中​​,返回的值本身就是一个函数。该函数涉及引用参数" increment"和一个局部变量,"当前"。

我会考虑将闭包的概念与作为第一类对象的函数概念混为一谈。这两件事确实是分开的,尽管它们具有协同作用。

作为一个警告,我不是一个基本人格的形式主义者,而且我对术语非常糟糕,所以这可能应该用downvotes来淋浴。

答案 2 :(得分:1)

我会尝试回答你的问题,因为你知道在面试过程中有什么关闭(从上面的评论中读到)。

首先,我认为你应该更加具体了解"否则"。究竟是怎么回事?

可能我们可以说一下这个noop功能的关闭:

function() {}

但似乎没有任何意义,因为没有变量会限制它的范围。

我认为即使这个例子也不太好考虑:

function closureDemo() {
    var localVar = true;
}
closureDemo();

由于它的变量将被释放,因为在此函数调用之后无法访问它,因此JavaScript之间没有区别,让我们说C语言。

再一次,既然你说你已经询问了访问中关闭的内容,我想你可以通过你在closureDemo()之后获得的外部函数来访问一些局部变量的例子会更好一些。先打个电话。像

function closureDemo() {
    var localVar = true;
    window.externalFunc = function() {
        localVar = !localVar;  // this local variable is still alive
        console.log(localVar); // despite function has been already run,
                               // that is it was closed over the scope
    }
}
closureDemo();
externalFunc();
externalFunc();

然后评论其他案例,然后得出最常见的定义,因为它更有可能让面试官同意你,而不是引用Flanagan并立即尝试找到你已经读过的页面更好地证明你的陈述或某事。 可能你的面试官只是认为你实际上并不知道闭包是什么,只是从书中读出定义。无论如何,祝你下次好运。

答案 3 :(得分:0)

定义是正确的。 封闭保持了它诞生的范围

考虑这个简单的代码:

getLabelPrinter = function( label) {
  var labelPrinter = function( value) {
      document.write(label+": "+value);
  }
  return labelPrinter; // this returns a function
}

priceLabelPrinter = getLabelPrinter('The price is');
quantityLabelPrinter = getLabelPrinter('The quantity is');

priceLabelPrinter(100);

quantityLabelPrinter(200);

//output:
//The price is: 100 The quantity is: 200  

https://jsfiddle.net/twqgeyuq/