今天做笔试题,好多关于JS闭包问题,就整理出来,分享一下。
首先,引用下所谓的“官方解释”:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
请注意加粗部分,会有益于你的理解。
来看例子1:
function a(){
var i = 1;
function b(){
alert(i);
}
return b();
}
var c = a(); c; // a();
例子2:
function a(){
var i = 1;
function b(){
alert(i);
}
return b;
}
var c = a(); c(); // a()();
上述两个例子的运行结果都是一样的,只不过应该会有很少人用例子2那样结尾a()()
那样的写法吧。嘻嘻,我也是今天才发现的。这样写的话,你是不是对函数后面的括号()
有了更深的理解呢?
没错,从上面我们可以看出来,函数声明定义时肯定少不了身份证()
,而当把一个函数名连带括号()
也赋给一个变量,这时的变量其实是指向了这个函数体,也就是说把函数体的指针(地址)赋给了此变量。像上面例子2结尾那样,a()()
中的前面部分a()
返回值(结果)是一个函数名(指向函数名的指针),也就是说不会执行。所以要在a()
后面再加一个()
,才会执行,相当于b()
。因为a()
的返回值是b
,a()
()
也就相当于b
()
。
插播结束,返回来说“闭包”问题。
继续看例子:
function a(){
var i = 1;
alert(i);
}
function b(){
alert(i);
}
b();
上面的例子是会报错的:
现在返回去继续想“闭包”,你好惊奇的发现,例1和例2里,变量c竟然可以弹出了
i
!它可是没有在变量c的同级作用域定义过啊!但是——因为“闭包”的存在:函数b()
以及函数a里的变量i
。
注意
上面提到的,“闭包”是包含着函数b()
以及变量i
,好多网上的文章只简单的提到了函数b()
,我认为,结合开篇中的“官方说法”,那种说法是不精确的。(变量也是表达式(闭包)的一部分)
至于闭包的作用,对于垃圾回收机制的好处云云,暂时还没有学习到,后续会继续更新补充。