- 闭包,通常有个比较标准的格式,我们先来感受下
function my() {
var a=1;//局部变量
}
alert(a);//报错,a is not defined,函数体外不可以访问
function my() {
var a=1;//局部变量
return function () {
alert(a);}//闭包
}
my()();//1
其实我觉得闭包的格式就是一个函数1体内镶嵌另一个函数2,可以通过这个函数2访问函数1的变量
-
这也引出了闭包的一个强大的作用,就是可以通过闭包外部访问函数内部的变量
-
闭包还有一个作用,在一个环境下同时出现两个变量,为了避免冲突,可以使用闭包,这样就只能访问闭包里的东西,其他就不能访问
- 举个例子
var n=2; function my() { var n=1; return function () { var n=3; return n; }//this is a 闭包 } alert(n);//2,这只能访问到全局变量n,函数内部无法访问 alert(my);//打印出来my这个函数 alert(my());//打印出来的是闭包,此时又为n赋值为3, alert(my()());//3,打印的是闭包里的变量
这里面赋了3个n值,但是他们互不影响
- js高级编程书上对于闭包是列出了这两段代码
var name='ly'; var obj={ name:'lyy', say:function () { //在这个时候没有使用闭包 return function () { return this.name; };//注意看return这个函数,并没有返回任何对象的调用,返回的只是this.name。并没有指明他的对象
} }; alert(obj.say()());//'ly'obj.say()返回一个匿名函数,这个时候,编译器会默认对象是window
这里只是调用obj的这个say方法,方法定义的是返回this.name
在这个时候,没有使用闭包,并不能访问到obj.name的值,所以this会自动理解为全局变量
```javascript
var name='ly';
var obj={ name:'lyy',
say:function () {
var that=this;//这个时候this指向的是obj
return function () {
return that.name; };//现在是一个闭包了,因为他调用了函数的变量了
}
};
alert(obj.say()());//'lyy'因为使用了闭包,这个时候that指向的是obj
- 最近在论坛上看到这样的一段代码,思考了很久,觉得挺有意义的
function my() {
var n=1;
return function() {
n++;
alert(n);
}
}
my()();//2,使用了闭包,n 的值为1
my()();//2,同样使用了闭包,闭包的作用就是让这些变量的值始终保持在内存中,所以n还是为1
var foo=my(); //创建了和my一样的函数
foo();//2,foo();使用了闭包
foo();//3,这个时候调用的n值已经是执行了一次方法的n值了,n=2;并没有使用闭包
只要把这两段代码弄懂了,闭包就差不多了,其实js不存在什么闭包的,每个都是对对象的调用,函数也不过是特殊对象一种而已
- 在闭包中,其实就是需要弄清全局变量和局部变量
- 在上一段小代码,方便理解全局变量和局部变量
fuction my() {
n=2;
var n=1;
alert(n);
}
alert(n);//2,这是全局变量
my();//1,这是局部变量,my这个函数要求打印局部变量n,因为alert是出现在n=1之后,所以临近原则是1
//如果是出现在n=2之后,临近原则,出现的就是2
- 最近发现了一段代码,叫循环中的闭包,先来感受下
- 代码
function f() {
var a=[];
var i;
for(i=0;i<3;i++) {
a[i]=function () { //这里的i是数组的arguments,数组的长度为3,0,1,2
return i; } //这里的i不是上述的i,指的是for循环执行后的i,for循环是先比较,再执行,所以返回的是最终循环停止的结果3
}
return a;
}
var m=f();
m[0]();//3
m[1]();//3
m[2]();//3
console.log(m);//返回的是一个数组
初次看这段代码,觉得一头雾水,琢磨了很久,还是有那么一点点领悟
首先弄清楚f()返回的就是一个数组,m是创造的一个函数实例,同样返回的是数组
再来看看a[i]这个函数,里面包含了一个闭包,返回的是i
接下来看循环,a[i]返回的就是a[0];a[1];a[2];return i返回的一直就是3,就是说这个函数返回的都是3
why?
难道不应该是0,1,2,最起码也是2啊,3是如何得来的?可以先看一个例子
function f() {
for (var i=0;i<3;i++) {
var a=[i];
}
console.log(i); //3,在这里据不得不说传值和传引用的区别了,这里返回的只是一个值
console.log(a); //2,这里返回的是数组
} f();
那么这个就说得通了,m()的返回就是一个数组,m[i]=function () { return i };在浏览器测试中就可以发现闭包下面的i一直都是3, 变的只是m[i],但这并不影响,其实说这段代码存在一个很大的bug一点也不为过,在写代码的时候没有考虑值的传入和数组的引用
- 来一段修改后的正常代码
function f() {
var a=[];
var i;
for(i=0;i<3;i++) {
a[i]=(function (x) {
return function() {
return x; //闭包
}
})(i); //在函数中直接传入i的值,
}
return a;
}