JS闭包和闭包函数 – JavaScript高级教程

上一章JavaScript教程请查看:JS函数提升和变量提升
在本教程中,你将了解什么是JavaScript闭包以及它是如何工作的。
了解JavaScript闭包在JavaScript函数一章中,你已经了解到,在JavaScript中,变量的作用域可以是全局的,也可以是局部的,在ES6中,你还可以使用let关键字创建块范围的变量。
全局变量可以在程序的任何地方访问和操作,而局部变量只能由它们声明的函数访问和操作。
但是,在某些情况下,你希望一个变量在整个脚本中都可用,但又不希望代码的任何部分都能够意外地更改其值。
让我们看看会发生什么,如果你试图实现这个使用全局变量:

// 全局变量 var counter= 0; // 一个专门用来操作'counter'变量的函数 function makeCounter() { return counter += 1; }// 调用函数 makeCounter(); console.log(counter); // : 1makeCounter(); console.log(counter); // : 2// 试图从外部操作'counter'变量 counter = 10; console.log(counter); // : 10

正如你在上面的示例中所看到的,计数器变量的值可以在程序中的任何位置进行更改,而无需调用makeCounter()函数(第17行)。
现在,让我们尝试用局部变量实现同样的事情,看看会发生什么:
function makeCounter() { // 本地变量 var counter= 0; // 操作'counter'变量 return counter += 1; }// 调用函数 console.log(makeCounter()); // : 1 console.log(makeCounter()); // : 1

在这种情况下,counter变量不能从外部操作,因为它是本地makeCounter()函数的变量,但是后续调用函数之后它的值也不会增加,因为每次我们调用这个函数重置计数器变量的值,你可以清楚地看到在上面的例子中(第11行)。JavaScript闭包可以解决我们的问题。
function makeCounter() { var counter = 0; // 内部函数 function make() { counter += 1; return counter; } return make; }/* 执行makeCounter()函数并将返回的值存储在myCounter变量中 */ var myCounter = makeCounter(); console.log(myCounter()); // : 1 console.log(myCounter()); // : 2

在上面的例子中可以看到,内部函数make()是从外部函数makeCounter()返回的。因此,myCounter的值是内部的make()函数(第14行),调用myCounter可以有效地调用make()。在JavaScript中,函数可以赋值给变量,作为参数传递给其他函数,可以嵌套在其他函数中。
你还会注意到,内部函数make()仍然能够访问外部函数中定义的计数器变量的值,即使makeCounter()函数已经完成执行(第14行)。这是因为JavaScript表单闭包中的函数。闭包在内部存储对其外部变量的引用,并且可以访问和更新它们的值。
在上面的例子中,make()函数是一个闭包,它的代码引用外部变量计数器。这意味着无论何时调用make()函数,其中的代码都能够访问和更新计数器变量,因为它存储在闭包中。
最后,由于外部函数已经完成执行,所以代码的其他部分不能访问或操作计数器变量。只有内部函数可以独占访问它。
前面的例子也可以用匿名函数表达式来写,就像这样:
// 匿名函数表达式 var myCounter = (function() { var counter = 0; // 嵌套的匿名函数 return function() { counter += 1; return counter; } })(); console.log(myCounter()); // : 1 console.log(myCounter()); // : 2

提示:在JavaScript中,所有函数都可以访问全局作用域,以及它们上面的作用域。由于JavaScript支持嵌套函数,这通常意味着嵌套函数可以访问更高范围内声明的任何值,包括其父函数的范围。
注意:只要应用程序(即web页面)存在,全局变量就存在。然而,局部变量的生命周期很短,它们是在调用函数时创建的,在函数执行完后立即销毁。
创建Getter和Setter函数【JS闭包和闭包函数 – JavaScript高级教程】在这里,我们将创建一个变量secret,并使用闭包保护它不被外部代码直接操作。我们还将创建getter和setter函数来获取和设置它的值。
此外,setter函数还将快速检查指定的值是否是数字,如果不是,则不会更改变量值。
var getValue, setValue; // 自执行函数 (function() { var secret = 0; // Getter函数 getValue = http://www.srcmini.com/function() { return secret; }; // Setter函数 setValue = function(x) { if(typeof x ==="number") { secret = x; } }; }()); // 调用函数 getValue(); // : 0 setValue(10); getValue(); // : 10 setValue(null); getValue(); // : 10

提示:自动执行的函数也称为立即调用的函数表达式(IIFE)、立即执行的函数或自动执行的匿名函数。

    推荐阅读