Definition of 'closures'

Definition of 'closures'

本文关键字:closures of Definition      更新时间:2023-09-26

让我问一个问题。这与JavaScript中的闭包有关,但与它们的工作方式无关。

David Flanagan在他的"JavaScript最终指南第6版"中写道:

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

这是正确的吗?我能把每个函数(函数对象+它的作用域)都称为"闭包"吗?

堆栈的标签"闭包"上写着:

闭包是一类函数,它引用(关闭)定义它的范围中的变量 如果闭包在其定义范围结束后仍然存在,那么它关闭的变量也将继续存在

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

问题是: 为什么这么多开发人员不这么认为?这个理论有错吗?难道不能作为一般定义吗

从技术上讲,所有函数都是闭包。但是,如果函数没有引用任何自由变量,那么闭包的环境是空的。只有当存在需要与函数代码一起保存的封闭变量时,函数和闭包之间的区别才是有趣的。因此,通常将不访问任何自由变量的函数称为函数,而将访问闭包的函数则称为函数,这样您就可以了解这种区别。

这是一个很难确定的术语。一个简单地声明的函数只是一个函数。关闭的原因是调用函数。通过调用函数,可以为传递的参数和声明的局部变量分配空间。

如果一个函数只是返回一些值,而这个值只是简单的东西(比如,什么都没有,或者只是一个数字或字符串),那么闭包就会消失,它真的没有什么有趣的地方。然而,如果一些对参数或局部变量的引用(大多数都是相同的)"转义"了函数,那么闭包—分配给局部变量的空间,以及父空间链—留下来。

以下是一些引用可以"逃离"函数的方法:

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"和局部变量"current"的代码。

我会对闭包的概念和函数是一类对象的概念混为一谈表示异议。这两件事确实是分开的,尽管它们是协同作用的。

需要注意的是,从基本性格来看,我不是一个形式主义者,我对术语也很糟糕,所以这可能会遭到大量的反对票。

我会尽量回答你的问题,因为我知道你在面试中被问到了什么是闭包(从上面的评论中阅读)。

首先,我认为你应该更具体地说"另谋高就"。具体如何?

也许我们可以谈谈这个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();

然后评论其他案例,然后得出最常见的定义,因为这更有可能让面试官同意你的观点,而不是引用弗拉纳根的话,并立即尝试找到你读过的页面,作为你陈述或其他事情的更好证明。也许你的面试官只是认为你实际上不知道闭包是什么,只是读了书中的定义。无论如何,我祝你下次好运。

定义是正确的。关闭保留了它诞生的范围

考虑一下这个简单的代码:

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/