标签:
在程序设计语言中,闭包(即词法闭包lexical closures或函数闭包function closures)是用一等函数(first class)实现词法作用域(lexically scoped)名称绑定(name binding)的一种技术。操作上说,一个闭包是一个用来存储一个函数及其环境的一条记录(record),这个环境会在闭包创建的时候,在函数的每个自由变量(free variable——在局部使用,但是定义在外部作用域)与其值或名称绑定的存储区之间建立一个映射。不同于一般普通函数(plain function),即使当函数在其作用域外被调用时,闭包仍然允许函数通过闭包的引用访问(存取)捕获的变量(captured variables)。
以上释义比较抽象,我们先用JavaScript语言举一个简单的例子并加以说明(我在此采用维基百科中说给出的例子并加以改写),在段代码与以上概念之间建立一个映射,让大家有一个直观的概念。稍后,我们再来理解这些概念是什么、如何理解?
function startAt(CAPTURED) { function incrementBy(i) { return CAPTURED + i; } return incrementBy; }
以上的代码片段定义了一个高阶函数(higher-order function)startAt,这个函数接收一个参数CAPTURED(我将由闭包捕获的变量大写。这并不是JavaScript的标准实践,也不鼓励这样做,这里只是为了方便说明[4])和一个内部函数(nested function) incrementBy。尽管CAPTURE变量不是incrementBy的局部变量,由于incrementBy处于CAPTURED变量的词法作用域中,这个内部函数可以访问变量CAPTURED。函数startAt返回了一个包含函数incrementBy的闭包,这个函数把变量i与CAPTURED相加然后和CAPTURED在当前(this)调用startAt的一个引用返回,所以当incrementBy被调用时会知道当前的CAPTURED的值。
应用以上函数得到运行结果如下:
var startAt10 = startAt(10); // closure1 var startAt100 = startAt(100); // closure2 startAt10(1); >> 11 startAt100(1); >> 101
我们注意到,因为startAt返回一个函数,所以变量startAt10 和 startAt100 是属于函数类型。运行startAt10(1)会返回11,运行startAt100(1)会返回101。尽管startAt10和startAt100都关联到同一个函数incrementBy,相关的环境却不同,调用闭包会将CAPTURED与不同值的不同变量绑定,因此执行函数会得到不同的结果。
标签:
原文地址:http://www.cnblogs.com/frontendBY/p/4770756.html