JavaScript闭包
JavaScript变量可以属于全局作用域或全局作用域。全局变量可以通过闭包实现本地(私有)。
全局变量
一个函数可以访问函数内定义的所有变量,如下所示:
function myFunction() {
var a = 4;
return a * a;
}
但是也可以访问函数外部定义的变量,如下所示:
var a = 4;
function myFunction() {
return a * a;
}
在最后一个示例中,a是全局变量。在网页中,全局变量属于window对象。页面中(和窗口中)的所有脚本都可以使用(和更改)全局变量。在第一个示例中,a是局部变量。局部变量只能在定义它的函数内使用。它隐藏在其他函数和其他脚本代码中。具有相同名称的全局变量和局部变量是不同的变量。修改一个,不修改另一个。
局部变量生命周期很短
只要您的应用程序(您的窗口/您的网页)存在,全局变量就会存在。局部变量的寿命很短。它们在调用函数时创建,并在函数完成时删除。
假设您想使用变量来计算某些内容,并且您希望此计数器可用于所有函数。您可以使用全局变量,并使用一个函数来增加计数器:
// 初始化 counter
var counter = 0;
// 函数中 counter 递增
function add() {
counter += 1;
}
// 调用 add() 3 次
add();
add();
add();
// counter 现在应该是 3
上述解决方案存在问题:页面上的任何代码都可以更改计数器,而无需调用add()。计数器应该是add()函数的局部变量,以防止其他代码更改它
// 初始化 counter
var counter = 0;
// 增加计数器的函数
function add() {
var counter = 0;
counter += 1;
}
// 调用三次 add()
add();
add();
add();
//计数器现在应该是3.但它是0
它没有用,因为我们显示全局计数器而不是本地计数器。我们可以通过让函数返回它来删除全局计数器并访问局部计数器:
// 增加计数器的函数
function add() {
var counter = 0;
counter += 1;
return counter;
}
// 调用三次 add()
add();
add();
add();
//counter 现在应该是3.但它是1。
它没有用,因为我们每次调用函数时都会重置本地计数器。JavaScript内部函数可以解决这个问题。
JavaScript嵌套函数
所有函数都可以访问全局范围。 实际上,在JavaScript中,所有函数都可以访问“上面”的范围。JavaScript支持嵌套函数。嵌套函数可以访问它们“上方”的范围。在此示例中,内部函数plus()可以访问counter父函数中的变量:
function add() {
var counter = 0;
function plus() {counter += 1;}
plus();
return counter;
}
如果我们能够从外部使用plus()这个函数,这可以解决反制困境。我们还需要找到一种counter = 0只执行一次的方法。我们需要闭包。
闭包函数
还记得自我调用的功能吗?这个函数有什么作用?
var add = (function () {
var counter = 0;
return function () {counter += 1; return counter}
})();
add();
add();
add();
// counter 现在是 3
示例说明:
为变量add分配自调用函数的返回值。自调用函数只运行一次。它将计数器设置为零(0),并返回一个函数表达式。这样添加成为一种功能。“精彩”部分是它可以访问父范围中的计数器。这称为JavaScript闭包。它使函数具有“ 私有 ”变量。计数器受匿名函数范围的保护,只能使用add函数进行更改。
闭包是一个可以访问父作用域的函数,即使在父函数关闭之后也是如此。