闭包的学习
一.动态语言与闭包
1.语法域和执行域
所谓语法域,是指定义某个程序段落的区域,所谓执行域,是指调用某个程序段落时所影响到的区域。
静态语言中,语法域与执行域基本是确定的,但是在动态语言中语法域与执行域基本一般不同,执行域通常比语法域大很多。
2.一个体现闭包本质的例子
所谓闭包,是指语法域位于某个特定的区域,具有持续参考(读写)位于该区域内自身范围之外的执行域上的非持久型变量值的能力的段落!这些外部执行域的非持久型变量神奇地保留他们在闭包最初定义是的值。javascript闭包通常是通过定义在函数内部体function来实现的。
<html>
<head>
</head>
<body>
<scritp type="text/javascript">
<!--
//这是一个普通函数
function A(a){
reutrn a;
}
//这是一个返回值是函数的函数
function B(b){
return function(){
return b;
}
}
var x = A(10);
/*
因为A除了返回a外什么没做,执行A()函数后,调用堆栈被销毁
没有产生闭包,或者说在调用瞬间产生了闭包,然后马上释放
*/
var y = B(20);
//因为B返回了一个匿名函数,他访问到B()被调用时产生的环境
// 在他的环境中,b=20,因此y()的返回结果是20
var z = B(30);
//同样在他的环境中b=30,因此z()的返回结果是30
alert(x);
alert(y());
alert(z());
-->
</script>
</body>
</html>
在这里y(),z()结果不同,因此两次访问的不是同一个b值,在这里应注意B()调用已经结束,但是局部变量没有销毁,所以能调出来b的值!
下面给出一个实例
function dice(count,side){/*count定义筛子的数量,side定义筛子的面数*/
var ench = Match.floor(Match.random()*6);
return function(){
var score = 0;
for(var i = 0;i < count;i++){
score += Match.floor(Math.random()*side) + 1;
}
return score + ench;
}
}
var d1 = dice(2,6);
var d2 = dice(1,20);
我通常认为闭包是一种引用结构,在javascript中 闭包可以理解为一种,“函数实例的引用”。
3.闭包的形式和特点
闭包,当然就是闭的,他能控制外包作用域的能力但又能防止外部作用域对闭包的反向控制。除非闭包对外提供接口。
4.闭包和面向对象
下面给出一个例子 其实用闭包可以来定义私有变量
<html>
<head>
</head>
<body>
<script type="text/javascript">
<!--
function dwn(s){
document.write(s+"<br/>");
}
function Foo(a){
//私有的函数
function _pC(){
return a;
}
//公有函数,通过它产生的闭包可以访问对象内部的私有方法_pC()
this.bar = function (){
dwn("foo" + _pC() +"!")
}
}
var obj = new Foo("bmm");
obj.bar();
-->
</script>
</body>
</html>
5.其他形式闭包
匿名函数 jquery 就是这样的一个例子。
一个嵌套的匿名函数:javascript:(function(i){return function(j){i + j}})(2)(3);
6.不适合使用闭包的场景
闭包最大的特点是能访问外包作用域,如果你要访问的外部作用域有很多变量,但是你只用到其中的一小部分建议不要使用闭包,因为闭包不能及时的释放引用作用域的内存,所有非常占内存