闭包
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
闭包
闭包是指有权访问另一个函数作用域中的变量的函数。
变量作用域
变量的作用域有两种:全局变量和局部变量。
Javascipt语言的函数内部可以访问全局变量,但是在全局作用域中无法读取函数内部的变量。
var a = 1;
function b(){
var c = 2;
alert(a);//a
}
alert(c);//error
在函数内部声明变量,需要使用var 命令,否则就声明了一个全局变量。
function a(){
b = 1;
}
alert(b);//1
在函数外部读取其内部变量
如何在函数外部读取其内部变量?由于JavaScript有’链式作用域’的概念,子对象会一级一级向上寻找父对象的变量,所以,可以在函数内部再定义一个函数,返回内部这个函数的父对象变量:
function a(){
var n = 1;
function b(){
alert(n);
}
return b;
}
var c = a()();//1;
这样,实际上我们在全局作用域中访问了a函数内部变量n。
闭包的概念
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成”定义在一个函数内部的函数”。
闭包的作用
闭包除了在函数外部可以访问内部变量以外,还可以让变量一直保存在内存中。
function a(){
var n= 1;
function b(){
n++;
alert(n);
}
return b;
}
var c = a();
c();//2
c();//3
由于b函数被赋给了c变量,而c变量是一个全局变量,所以b函数始终在内存中,而b函数依赖于a函数,所以a函数内部变量也存在于内存中,不会被垃圾回收机制回收。所以变量n会始终保存在内存中。
使用闭包的注意事项
在使用闭包后,会消耗大量内存,导致严重的性能问题,所以在退出函数之前应该将函数的局部变量全部删除。
例如要访问一个DOM对象:
<div id="ele" class="content"></div>
function getId(){
var element = document.getElementById('ele');
element.onclick = function(){
alert(element.id);
}
}
getId();//'ele'
由于element对象始终处于活动状态,因此就会导致无法减少element 的引用数。只要匿名函数存在,element 的引用数至少也是1,因此它所占用的内存就永远不会被回收。可以改写函数如下:
function getId(){
var element = document.getElementById('ele');
var id = element.id;
element.onclick = function(){
alert(id);
}
element = null;
}
getId();//'ele'
这样,在使用完之后把element 变量设置为null。这样就能够解除对DOM 对象的引用,顺利地减少其引用数,确保正常回收其占用的内存。
闭包和this指向的问题
this 对象是在运行时基于函数的执行环境绑定的:在全局函数中,this 等于window,而当函数被作为某个对象的方法调用时,this 等于那个对象。不过,匿名函数的执行环境具有全局性,因此其this 对象通常指向window。
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()()); //"The Window"
每个函数在被调用时都会自动取得两个特殊变量:this 和arguments,由于匿名函数无法取得其外部函数的this对象,所以它直接向上寻找到了活动的window对象,并返回其name属性的值。
不过,把外部作用域中的this 对象保存在一个闭包能够访问到的变量里,就可以让闭包访问该对象了:
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()()); //"My Object"
在定义匿名函数之前,我们把this对象赋值给了一个名叫that 的变量。而在定义了闭包之后,闭包也可以访问这个变量,因为它是我们在包含函数中特意声名的一个变量。即使在函数返回之后,that 也仍然引用着object,所以调用object.getNameFunc()()就返回了”My Object”。
同样的,如果想访问作用域中的arguments 对象,必须将对该对象的引用保存到另一个闭包能够访问的变量中。
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |