快速业务通道

闭包的概念、形式与应用

作者 佚名技术 来源 Linux系统 浏览 发布时间 2012-05-07
um i
end

do10times(addsum)
print(sum)


这里我们看到,函数 addsum 被传递给函数 do10times,被并在 do10times 中被调用10次.不难看出 addsum 实际的执行点在 do10times 内部,它要访问非局部变量 sum,而 do10times 并不在 sum 的作用域内.这看起来也是无法正常执行的.

这两种情况所面临的问题实质是相同的.在这样的语言中,如果按照作用域规则在执行时确定一个函数的引用环境,那么这个引用环境可能和函数定义时不同.要想使这两段程序正常执行,一个简单的办法是在函数定义时捕获当时的引用环境,并与函数代码组合成一个整体.当把这个整体当作函数调用时,先把其中的引用环境覆盖到当前的引用环境上,然后执行具体代码,并在调用结束后恢复原来的引用环境.这样就保证了函数定义和执行时的引用环境是相同的.这种由引用环境与函数代码组成的实体就是闭包.当然如果编译器或解释器能够确定一个函数在定义和运行时的引用环境是相同的(注 3),那就没有必要把引用环境和代码组合起来了,这时只需要传递普通的函数就可以了.现在可以得出这样的结论:闭包不是函数,只是行为和函数相似,不是所有被传递的函数都需要转化为闭包,只有引用环境可能发生变化的函数才需要这样做.

Empire CMS,phome.net

再次观察上面两个例子会发现,代码中并没有通过名字来调用函数 inc_count 和 addsum,他们根本不需要名字.以第一段代码为例,它可以重写成下面这样:


清单 3. 闭包示例3

function make_counter()
local count = 0

return function()
count = count 1
return count
end
end

c1 = make_counter()
c2 = make_counter()

print(c1())
print(c2())


这里使用了匿名函数.使用匿名函数能使代码得到简化,同时我们也不必挖空心思地去给一个不需要名字的函数取名字了.

上面简单地介绍了闭包的原理,更多的闭包相关的概念和理论请参考参考资源中的"名字,作用域和约束"一章.

一个编程语言需要哪些特性来支持闭包呢,下面列出一些比较重要的条件:

函数是一阶值;
函数可以嵌套定义;
可以捕获引用环境,并
把引用环境和函数代码组成一个可调用的实体;
允许定义匿名函数;
这些条件并不是必要的,但具备这些条件能说明一个编程语言对闭包的支持较为完善.另外需要注意,有些语言使用与函数定义不同的语法来定义这种能被传递的"函数",如 Ruby 中的 Block.这实际上是语法糖,只是为了更容易定义匿名函数而已,本质上没有区别.

借用一个非常好的说法来做个总结(注 4):对象是附有行为的数据,而闭包是附有数据的行为.

闭包的表现形式

虽然建立在相似的思想之上,各种语言所实现的闭包却有着不同的表现形式,下面我们来看一下闭包在一些常用语言中的表现形式.

JavaScript 中的闭包

JavaScript(ECMAScript)不是通用编程语言,但却拥有较大的用户群体,而 Ajax 的流行也使更多的人关注 JavaScript.虽然在进行 DOM 操作时容易引发循环引用问题,但 JavaScript 语言本身对闭包的支持还是很好的,下面是一个简单的例子:


清单 4. JavaScript

function addx(x) {
return function(y) {return x y;};
}

add8 = addx(8);
add9 = addx(9);

alert(add8(100));

Empire CMS,phome.net

alert(add9(100));


Ruby 中的闭包

随着 Ruby on Rails 的走红,Ruby 无疑是时下炙手可热的语言之一,Ruby 吸取了很多其他语言的优点,是非常优秀的语言,从这一点来看,很难说清是 Rails 成就了 Ruby 还是 Ruby 成就了 Rails.

Ruby 使用 Block 来定义闭包,Block 在 Ruby 中十分重要,几乎到处都可以看到它的

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号