虽然时不时的写js或者jq,也接触闭包,但是没有仔细研究过闭包,前段时间接过一个华腾的电话面试,问起了闭包,我没做任何准备,我只知道闭包能解决什么问题,但是问我什么闭包,怎么实现闭包我却没能答上来,所有我今天查阅了一些资料,自己整理一些,但是发现一个老外的帖子讲的比我的好,我就简单翻译讲解一下。
首先老外的这个地址是:http://stackoverflow.com/questions/111102/how-do-javascript-closures-work;
- 什么是闭包:
官方解释是,指一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
官方这个解释太过于术语,我相信可以直接看懂的没几个人,我看了好多遍,写例子才懂了点,下来我写一个简单的例子,仔细分一下这句话:
function a(){
var index = 0;
function b(){
alert(++index);
}
return b;
}
var c = a();
c();
这块代码相信大家在很多地方见过,这个代码是很典型的闭包,首先我解释一下这块代码
一个函数a,函数a包含一个变量index,函数a中有一个内部函数b,函数a返回了函数b;
var c = a();这句代码执行之后 就把函数b的引用指向了c,并没有调用函数b
c();这句代码调用了函数b
当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。(这个变量值得是c,c是b的引用)
调用b也可以这样写a()(),
现在就使用这块代码分析一下官网对闭包的定义,
“指一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。” 这句话去掉各种修饰词之后就是“指一个表达式“
因此我们断定闭包就是个函数,但是这块代码里面有a和b两个函数,再看定义“拥有许多变量”,因此断定这里的a函数就是个闭包,再看定义“绑定了这些变量的环境”这里就断定了定义中所指的环境就是函数b,所以合起来解释这块代码就是:
闭包是指拥有变量index和绑定了变量index的函数b的函数a。
现在应该对闭包有一点点感觉了吧,但是还是有点晕,晕的应该是为什么说这就是闭包吧?
- 闭包的应用场景
- 保护函数内的变量安全:在回头看例子,函数a中的变量index是不能通过其它方式访问的,因此保护了index的安全。
- 在内存中维持一个变量:由于闭包,函数a中index的一直存在于内存中,因此每次执行c(),都会给index自加1。
通过闭包的应用场景介绍和对以上定义的分析相信大家对闭包,现在了解的差不多了,下来这块代码看完你就应该完全掌握闭包了,马上来看一下:
function makeKitchen (t) {
return {
a: function() {
alert("a_"+t);
},
b: function() {
alert("b"+t);
},
c: function() {
alert("c"+t);
}
};
}
var mk = makeKitchen('ly仔');
mk.a();//a仔
mk.b();//b仔
mk.c();//c仔
这块代码是不是很熟悉,网上好多小插件都类似有这样的写法,没错这就是闭包。一样,首先读一下代码回想一下官方对闭包的定义:
一个带参数的函数makeKitchen,返回了一个对象{},这个对象里面包含了3个函数,函数a、b、c,然后下面是调用 的方法。在这里我没有定义变量,只有定义中所说的绑定变量的环境,就是return的这个对象,
重点理解一下几句话:
var mk = makeKitchen('ly仔');
把函数makeKitchen中的对象的引用给了变量mk
mk.a(); mk.b(); mk.c();
然后使用mk即函数makeKitchen中的对象的引用,访问函数makeKitchen中对象中的成员,然后把上面两句话整合一下就是:
函数makeKitchen中的内部函数被外部通过makeKitchen内部对象的引用访问,就创建了闭包;函数a、b、c只能通过返回的对象的引用调用,这就是闭包 。
现在应都理解闭包了吧。