闭包:
1.定义:
官方解释:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
理解:闭包就是能够读取其他函数内部变量的函数。由于在javascript语言中,
只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成:‘定义在一个函数内部的函数’。
所以,本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
要理解闭包,就得先理解JavaScript特殊的变量作用域,变量的作用域无非就两种:全部变量和局部变量
js作用域:全局作用域和函数作用域
2.特点:
1).作为一个函数变量的引用,当函数返回时,其处于激活状态。
2).一个闭包就是当一个函数返回时,一个没有释放资源的栈区。
简单的闭包如下:
function (){
var n=100;
return function(){
alert(++n);
}
}
函数执行时创建了一个内部函数,这个内部函数作为返回值,或以某种方式保留下来(属性),之后才调用,
这就会形成了闭包。通俗来讲,JS所有的function都是一个闭包。
3.用途场景
1)匿名自执行函数
我们创建了一个匿名函数,并立即执行它,由于外部无法引用他内部的变量,因此在函数执行完后会立刻释放资源,
关键是不污染全局对象。
代码如下:
(function(){
var days=['sun','mon','tue','wed','thu,,'fri','sat]
today = new Date();
msg ='Today is '+ days[today.getDay()]+','+today.getDate()
alert(msg);
}())
2)结果缓存
我们在开发过程中会遇到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,
那么我们就需要将计算出来的值存储起来,当调用这个函数时候,首先在缓存中查找,如果找不到,则进行计算,
然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包就可以做到这点,因为他不会释放外部的引用,
从而函数内部的值可以得以保留。
3)封装
var person=function (){
//变量作用域为函数内部,外部无法访问
var name = 'ruirui.xu';
return {
getName:function(){
return name;
}
setName :function(){
name = newName;
}
}
}()
在person之外的地方无法访问其内部变量,而通过提供闭包的形式访问。
alert(person.name)//直接访问,结果undefined
alert(person.getName())//ruirui.xu
person.setName('xuruirui')
alert('person.getName())//xuruirui
4)实现类和继承
var person=function (){ //变量作用域为函数内部,外部无法访问 var name = 'ruirui.xu'; return { getName:function(){ return name; } setName :function(){ name = newName; } } }()
var p = new Person();p.setName("Tom");alert(p.getName());//Tomvar Jack = function(){};//继承自PersonJack.prototype = new Person();//添加私有方法Jack.prototype.Say = function(){ alert("Hello,my name is Jack");};var j = new Jack();j.setName("Jack");j.Say();alert(j.getName());//Jack
4.优缺点
优点:
1)可以读取函数内部的变量
2)可以让这些局部变量保存在内存中(因为这些变量一直在外部被引用)
缺点:
1)因为闭包会使得函数中的变量都保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能会导致内存泄漏。
解决方法:在退出函数之前,将不适用的局部变量全部删除
2)闭包会在父函数外部改变父函数内部变量的值
所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
5.栗子
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){return this.name;};
}};
alert(object.getNameFunc()());
//the window
var name = "The Window";
var object = {name : "My Object",
getNameFunc : function(){
var that = this;
return function(){return that.name;};
}};
alert(object.getNameFunc()());
//My Object