我们都知道一个概念。
在JS当中,一个函数可以访问其外部的变量资源。
但以下这种情况会出错。
function m1(){
var a = 100;
console.log(a++);
}
function m2(){
console.log(a++); //这里无法访问a
}
如果,我们想在m2的作用域里,访问m1里的变量,就像下面这样:
首先,我们可以在m1的内部创建一个函数m3
function m1(){
var a = 100;
function m3(){
console.log(a++);
}
}
m3可以正常访问a,接下来我们增加一个return操作。
function m1(){
var a = 100;
return function m3(){
console.log(a++);
}
}
既然有了返回值,那我们不妨接收一下,继续编写代码如下:
function m1(){
var a = 100;
return function m3(){
console.log(a++);
}
}
var _m3 = m1();
我们执行了函数m1, 并将返回值赋值给_m3,
那么目前_m3和m3函数是等价的,即它们是同一个函数。
有了_m3,一切都好办了。我们继续编写代码
function m1(){
var a = 100;
return function m3(){
console.log(a++);
}
}
var _m3 = m1();
function m2(){
_m3();
}
因为_m3是全局变量,因此m2可以调用_m3
也就等价于m2间接的,访问到了变量a
通常,我们管m3,叫做一个『 闭包函数 』
下面列举几个常见的闭包场景:
01
for(var i=0; i<list.length; p="" i++){<="">
var item = list[i];
item.onclick = (function(num){
return function(){
//......
}
})(i);
}
02
function (){
var that = this;
setTimeout(function(){
//......
},2000)
}
03
function User(){
var _age = 0;
this.getAge = function(){
return _age;
}
this.setAge = function(age){
this._age = age;
}
}
04
(function(){
var cache = [...];
return {
get : function(){
//...
}
};
})()
05
(function(){
var t = null;
return function(){
if(!t){
t = create();
}
}
})()
为了创造闭包,有时候会写函数自调用
可以不这么麻烦么??
当然,那就是使用let。
例如
for(let i=0; i<list.length; p="" i++){<="">
let item = list[i];
item.onclick = function(){
console.log(i);
//观察变量i的值
};
}
关于闭包的疑问
当函数m1执行完成的时候,内部的变量a,理论上应该被回收掉了。
可是为什么变量a依然可以被访问呢?
主要是因为,m3还在引用它
垃圾回收器显然不会回收一个依然被引用的变量。
除非这个变量,已经无人引用,即是说,它已经无法再内存里被找到。
此时才可以当做垃圾处理。
不过m3可以访问变量a这种规则,并不是在所有编程语言里都生效的。因此,这也算是JS的特性之一。