JavaScript 中的闭包






3.72/5 (28投票s)
对 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()
,则会创建一个新的闭包(堆栈帧!)。 旧的 gAlertNumber
、gIncreaseNumber
、gSetNumber
变量将被新的函数覆盖,这些函数具有新的闭包。
摘要
- JavaScript 中的闭包就像保留所有局部变量的副本,就像函数退出时一样。
- 最好认为闭包总是在进入函数时创建的,并且局部变量被添加到该闭包中。
- 每次调用具有闭包的函数时,都会保留一组新的局部变量(假设该函数包含一个函数声明在其内部,并且对该内部函数的引用要么被返回,要么以某种方式保留了外部引用)。