JavaScript的语言特性 — 闭包
闭包(closure)意味着内层的函数可以引用存在于包围它的函数内的变量,即使外围函数的执行已经终止。[code lang="js"]
// 查找 id 为 'main' 的元素
var obj = document.getElementById("main");
// 修改它的 border 样式
obj.style.border = "1px solid red";
// 初始化一个在一秒后执行的回调函数(callback)
setTimeout(function(){
// 它将隐藏此对象
obj.style.display = 'none';
}, 1000);
// 一个用于延时显示警告信息的通用函数
function delayedAlert( msg, time ) {
// 初始化一个封装的回调函数
setTimeout(function(){
// 它将使用包含本函数的外围函数传入的 msg 变量
alert( msg );
}, time );
}
// 用两个参数调用 delayedAlert 函数
delayedAlert( "Welcome!", 2000 );
[/code]
上面的例子演示了如何利用闭包避免糟糕的代码。displayAlert函数在函数作用域内使用了闭包,解决代码混乱的问题。
在一些函数式程序设计语言中,有一种称为Curry化(currying)的技术。本质上,Curry化是一种通过把多个参数填充到函数体中,实现将函数转换为一个新的经过简化的函数的技术。下面的代码通过向辽宁国外一个函数预填参数而创建了一个新函数。
[code lang="js"]
// 数字求和函数的函数生成器
function addGenerator( num ) {
// 返回一个简单的函数,求两个数字的和
// 其中第一个数字来自生成器
return function( toAdd ) {
return num + toAdd
};
}
// addFive 现在包含一个接受单一参数的函数
// 这个函数能求得 5 加上该参数的和
var addFive = addGenerator( 5 );
// 在传入参数 4 时,addFive 函数的结果是 9
alert( addFive( 4 ) == 9 );
[/code]
闭包还能解决另一个常见的JavaScript编写问题:开发新手经常会声明大量的全局变量,这些变量可能会影响其它的库,从而导致一些问题。通过自执行的匿名函数可以把所有原本属于全局的变量都隐藏起来。
[code lang="js"]
// 创建一个新的匿名函数,作为包装
(function(){
// 变量原本是全局的
var msg = "Thanks for visiting!";
// 将一个新函数绑定到全局对象
window.onunload = function(){
// 这个函数使用了隐藏的 msg 变量
alert( msg );
};
// 关闭匿名函数并执行之
}());
[/code]
最后,让我们看看使用闭包会遇到的一个问题。闭包允许引用父函数中的变量,但提供的值并非该循环变量创建时的值,而是在父函数范围内的最终值。这样带来的最常见的问题是在for循环中,有一个变量作为循环技术(如变量i),在这个循环里创建了新的函数,利用闭包来引用循环的计数器。问题是,在这个新的闭包函数被调用时,它引用的计数器的值是其最后一次的赋值,而不是期望的那个值。
[code lang="as3"]
// 一个 id 为 main 的元素
var obj = document.getElementById("main");
// 用于绑定的一个数组
var items = [ "click", "keypress" ];
// 遍历数组的每个元素
for ( var i = 0; i < items.length; i++ ) {
// 使用一个自执行的匿名函数来激发出作用域
(function(){
// 将一个函数绑定到该元素
obj[ "on" + items[i] ] = function() {
// item[i] 引用本 for 循环上下文所属作用域中的一个父变量
alert( "Thanks for your " + items[i] );
};
})();
}
[/code]
<img src="http://www.everyinch.net/wp-content/uploads/2013/11/js7-620x348.jpg" alt="js7" width="620" height="348" class="alignnone size-medium wp-image-3510" />
查看完整版本: JavaScript的语言特性 — 闭包
Tags: