参考:汤姆大叔的博文。
先看一个例子:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
</head>
<script type="text/javascript">
var Calculator=function()
{
return { //返回一个key-value的object对象
add:function(x,y)
{
return x+y;
},
sub:function(x,y)
{
return x-y;
}
}
}
var cal=new Calculator();
alert(cal.add(1,2)+" "+cal.sub(2,1));
</script>
<body>
</body>
</html>
这样每次要调用add方法时候都需要new一个Calculator对象。
匿名闭包:函数内部的代码一直在闭包内,在整个运行周期内,该闭包都保证了内部代码处于私有化状态。jQuery就是采用这种形式。下面是jQuery的代码:
(function( window, undefined ) {
//jQuery代码
})(window);
jQuery通过定义了一个匿名函数,创建了一个私有的命名空间,该命名空间上的变量和方法不会破坏全局的命名空间,同时也保证了jQuery创建的变量不会与导入其他的js程序创建的变量发生冲突。
上面的代码可以写成另外一种方式:
(function( window, undefined ) {
//jQuery代码
}(window));
参照上面这种方式修改第一个四则运算的代码,这个时候就不用通过new的方式调用add方法了,因为当使用这种方式后函数会自执行。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
</head>
<script type="text/javascript">
var Calculator=(function()
{
return {
add:function(x,y)
{
return x+y;
},
sub:function(x,y)
{
return x-y;
}
}
}());
alert(Calculator.add(1,2)+" "+Calculator.sub(2,1));
</script>
<body>
</body>
</html>
隐式全局变量:
一个变量不管有没有用过,JavaScript解释器会反向遍历作用域链来查找整个变量的var声明,如果没有找到var,解释器则假定该变量是全局变量,如果该变量用于了赋值操作的话,之前如果不存在的话,解释器则会自动创建它,这种特性就叫做隐式全局变量。
有了这种特性,这就是说在匿名闭包里使用或创建全局变量非常容易,不过比较困难的是,代码比较难管理,尤其是阅读代码的人看着很难区分哪些变量是全局的,哪些是局部的。
这时可以将全局变量作为一个参数然后传递到匿名函数中使用,如jQuery中的window参数,这个时候通过传入window变量,使得window由全局变量变成了局部变量,好处有两个:
1、根据隐式全局变量的特性,JavaScript解释器不用将作用域链回退到顶层作用域,可以更快的访问window;
2、查看jQuery的压缩版min.js包,会看到将window作为参数传入可以将压缩代码进行优化(将window优化成为a)。
(function(a,b){
//jQuery压缩代码
})(window);
如果我不仅仅想使用全局变量,而且想声明全局变量,这时我们可以通过匿名函数的返回值来返回这个全局变量。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
</head>
<script type="text/javascript">
var Introduce=(function()
{
var my={};
var privateName="xuzengqiang"; //私有名称,外部不能直接访问
my.name=privateName;
function sayHello(name) //私有方法,外部不能直接访问
{
alert("我叫"+name);
}
my.say=function()
{
sayHello(my.name); //但是这里可以调用内部处理的方法
}
return my;
}());
//Introduce.sayHello(); //错误,为私有方法
Introduce.say();
alert(Introduce.name); //可以直接调用
</script>
<body>
</body>
</html>
|