闭包,又见闭包。。。。

2017-01-10 10:03:12来源:segmentfault作者:hiscc人点击

1.闭包是指有权访问另一个函数作用域中的变量的函数。


上面这段话来自 javascript 高级程序设计 第三版 P178 。作者说闭包是一个函数,它有访问另一个函数作用域中的变量的能力。


2.函数访问它被创建时所处的上下文环境。这被称为闭包。


这段话来自 javascript 语言精粹 修订版 P38 。作者没有定义闭包为何物,只是说函数访问它被创建时的上下文环境,这种xxx(行为?过程?能力?) 被称为闭包。



3.1闭包是依赖于词法作用域编写代码而产生的结果


3.2闭包就是函数能够记住并访问它的词法作用域,即使当这个函数在它的词法作用域之外执行时



这两段话来自 You-Dont-Know-JS 作用域闭包 这一章,作者说闭包是一种结果。

闭包的一般定义

闭包是一种抽象概念,每个人对其理解不同,所以有了上面的几种解释。但大家讨论的确是同一个问题。


//step 1
function outer() {
var a = 'hello world';
function inner() {
return a ;
}
return inner();
}
// hello world
outer();

我们发现位于 outer 函数内的 inner 函数可以访问到另一个函数 outer 的作用域中的变量 a 。完美的闭包,对,闭包就这么简单。哈哈哈哈哈,本文结束!!!

闭包的由来

其实上面那段代码并不是大家真正所说的闭包,它其实是利用了函数作用域的特点--内层函数可以访问外层变量。这仅仅是闭包的一部分,闭包利用函数作用域达到了访问外层变量 a 的目的。


依据定义 1. 闭包可以说在代码 step1 中已经产生了。
我们接下来看 step2。


//step 2
function outer() {
a = 'hello world';
function inner() {
return a;
}
return inner();
}var c = outer();
// hello world
c;

这次我们执行 outer 函数, outer() 是一个函数对象,在内部只会返回 inner 函数的结果 a ,因为 inner 函数的存在每次执行 inner 便会对变量 a 进行引用,这导致变量 a 引用计数为 1 ,所以垃圾回收机制无法销毁变量 a 。我们便在函数执行完毕后依然访问到了变量 a。正规的写法如 step3


//step3
var c = (function() {
var a = 'hello world';
return {
inner : function() {
return a;
}
}
})();// hello world
c.inner();

我们利用自执行匿名函数把 inner 保存到变量 c 上,这时 c 就是 inner 函数,它可以访问到 inner 函数之外的变量 a 。变量 c 引用了变量 a 的值,导致变量 a 在函数执行后依然无法被销毁 。此时一个完整的闭包实现了, js 的垃圾回收机制由于闭包的存在无法销毁变量 a ,我们利用闭包,在函数外层还是访问到了 a ,保存了函数内部的细节。这就是闭包的全部。由此得来下面定义


4.闭包是阻止垃圾回收机制在内存中销毁变量的方法,使得在创建变量的执行环境外可以访问到该变量


上面这段话来自 单页Web应用 JavaScript 从前端到后端P49,个人认为这本书也是对闭包解释最为详尽生动的一本书。因为此书中大量使用了模块模式所以对闭包的解释十分详尽。


总结一下:闭包是由函数产生的,当我们把它赋值给一个变量后,一个完整的闭包出现了。它阻止了 js 的垃圾回收机制对函数内部变量的回收,导致函数内部变量的引用计数一直不为 0 ,无法被垃圾收集器回收。所以我们常听乱用闭包可能导致内存泄漏,就是因为闭包的这个特点。


函数作用域的特性让我们可以从内部取得外部的变量,而闭包提供了一种反向的操作可能--我们在外部也可以取得内部的变量


闭包是函数外可以访问函数内变量的实现


其它:
StackOverflow 闭包是什么
闭包的用处:You-Dont-Know-JS

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台