陈童的博客's Archivers

From everyinch on 2013-11-19 12:10:40

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:


©陈童的博客