65.9K
CodeProject 正在变化。 阅读更多。
Home

JavaScript 中的闭包

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.72/5 (28投票s)

2007年5月17日

CPOL

2分钟阅读

viewsIcon

49026

对 JavaScript 中闭包的介绍。

引言

定义 - 闭包是一个函数 连同其非局部变量引用环境。 << 参考链接 http://en.wikipedia.org/wiki/Closure_(programming)  >>

在 JavaScript 中,简单来说,如果在另一个函数内部创建一个函数,就是在创建闭包。

在大多数常见语言中,函数返回后,所有局部变量都将不再可访问,因为堆栈帧会被销毁。 考虑到这一点,闭包可以被认为是一个在函数返回时不会被释放的堆栈帧。

为什么要使用闭包

很多人问我为什么需要闭包。 我将尝试解释。

我遇到闭包的场景是在使用表格控件、文件对象等时。 通过闭包,我可以存储页面索引、行数等,以便在其他客户端函数中重用。 使用 FSO,我可以保存文件路径、计数等以供以后使用。 它不仅仅用于复杂的客户端控件。 考虑一下你的页面有很多控件,并且你正在执行客户端验证的情况。 每次你访问一个控件时

document.getElementById("controlname")  

整个页面控件树都会被搜索。 可以通过使用闭包并只保存一次控件来避免这种情况。 可重用性是闭包的关键优势。 希望我已经说服了一些人至少去了解闭包。

使用代码

请看下面的函数

function sayHello(name) {
    var text = 'Hello ' + name; // local variable
    var sayAlert = function() { alert(text); }
    return sayAlert;
}

现在我们以以下方式调用该函数

var say2 = sayHello("Sachin");
say2();

函数 sayHello() 返回一个指向函数 sayAlert() 的指针。

这里,当你在一个函数内部声明一个函数时,局部变量可以在从你调用的函数返回之后仍然可访问。 上面演示了这一点; 我们在从 sayHello() 返回后调用函数 say2()。 请注意,我们调用的代码引用了变量 text,它是函数 sayHello() 的一个局部变量

考虑下面的函数

function setupSomeGlobals() {

    // Local variable that ends up within closure
    var num = 666;

    // Store some references to functions as global variables
    gAlertNumber = function() { alert(num); }
    gIncreaseNumber = function() { num++; }
    gSetNumber = function(x) { num = x; }

}

这三个函数 gAlertNumber()gIncreaseNumber()gSetNumber(x) 共享对相同闭包的访问 - 当定义这三个函数时,setupSomeGlobals() 的局部变量。

可以通过连续调用这些函数来检查。

尝试以下序列

setupSomeGlobals() //value of num is 666 
gAlertNumber () //alerts 666 
gIncreaseNumber() 

gAlertNumber () //alerts 667 
gSetNumber (600) 
gAlertNumber () //alerts 600

如果我们再次调用 setupSomeGlobals(),则会创建一个新的闭包(堆栈帧!)。 旧的 gAlertNumbergIncreaseNumbergSetNumber 变量将被新的函数覆盖,这些函数具有新的闭包。

摘要

  • JavaScript 中的闭包就像保留所有局部变量的副本,就像函数退出时一样。
  • 最好认为闭包总是在进入函数时创建的,并且局部变量被添加到该闭包中。
  • 每次调用具有闭包的函数时,都会保留一组新的局部变量(假设该函数包含一个函数声明在其内部,并且对该内部函数的引用要么被返回,要么以某种方式保留了外部引用)。
© . All rights reserved.