闭包与作用域
谈到闭包就肯定要联系到作用域,因为产生闭包就肯定和作用域有关,一直听别人讲闭包,也一直在学习中不断地学习闭包,现在就根据自己的理解浅聊一下闭包。
一、作用域
变量作用域分为局部作用域和全局作用域
var a=1;//a是全局变量
var f=function (){
var b=2;//b是局部变量
c=3;//c 是全局变量(c 没用var声明,是一个全局变量)
a=4;//声明一个与与全局变量同名的局部变量a
alert(a);//a=4
alert(b);//b=2
}
f();
alert(c);//c=3
alert(b);//出错
作用域链:代码在一个环境中执行时会创建变量的一个作用域链
var f1=function(){
var local='local 1';
var f2=function(){
var local='local 2';
var f3=function(){
console.log(local);
};
f3();
}
f2();
}
f1();
// local 变量在f3()函数内找不到,继而在f2(),如果f2()中未定义就会到
f1()中寻找,一直向上到全局作用域,这样就构成了一条作用域链。
二、闭包
实现外部作用域访问内部作用域中变量的方法就是闭包,在Javascript语言中,只有函数内部的子函数才能读取局部变量,也就可以理解为定义在函数内部的函数
var a="global scope";
var f=function(){
var a="local scope";
function f1(){return a};
return f1();
}
f2=f;
f2();//f2()调用实现访问f内部变量
闭包最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,只有当相应的闭包对象被删除时才能在内存中被回收。一般只有在绝对必要时才建议使用闭包。
实现块级作用域
(function(){
......//这里是一个块级作用域
})();//块级作用域也称为私有作用域,可以模仿实现私有变量
通过闭包实现块级作用域和私有变量
function counter(){
var n=0;
return {
count:function(){return n++;},
reset:function(){n=1;}
};
}
var c=counter(),d=counter();
c.count();//0
d.count();//0
c.reset();
d.count();//1
c.count();//0 counter函数返回计算器对象,这个对象含两个方法,这两个方法都可以访问私有变量n。每次调用counter()就会创建一个新的作用域链和新的私有变量。
三Javascript的垃圾回收机制
在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。因为函数a被b引用,b又被a外的c引用,这就是为什么函数a执行后不会被回收的原因。