先看问题:
代码语言:javascript复制<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>变量作用域问题</title>
<script>
//程序员a写的代码
var a=123;
alert( a);
</script>
</head>
<body>
<script>
//程序员b写的代码
var a=89;
alert( a);
</script>
<script>
//程序员c写的代码
alert( a);
</script>
注意: 在这里, 三个程序员使用的都是同一个全局变量a, 造成了混乱。
</body>
</html>
解决方案: 每个程序员定义一个匿名函数,在自己的匿名函数中定义局部变量来使用:
代码语言:javascript复制<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>使用匿名函数解决变量作用域问题</title>
<script>
( function(){
//程序员a写的代码
var a=123;
alert( a);
})();
</script>
</head>
<body>
<script>
( function(){
//程序员b写的代码
var a=89;
alert( a);
})();
</script>
<script>
( function(){
//程序员c写的代码
alert( a);
})();
</script>
这里每个程序员定义了自己的匿名函数,在不同的函数中定义变量,这个变量就是一个局部变量。 <br />
用匿名函数将脚本包起来,可以有效控制全局变量,避免冲突。
</body>
</html>
但如果程序仍然要求在不同的程序员编写的代码之间共享一些数据怎么办,
代码语言:javascript复制<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>使用全局变量解决在多个匿名函数共享数据的问题</title>
<script>
//全局变量
var a=555;
</script>
<script>
( function(){
//程序员a写的代码
var a=123;
alert( a);
})();
</script>
</head>
<body>
<script>
( function(){
//程序员b写的代码
var a=89;
alert( a);
})();
</script>
<script>
( function(){
//程序员c写的代码访问的就是全局变量
alert( a);
})();
</script>
<hr />
在这里加入一个全局变量a的定义,这样,程序员c就可以访问全局变量。 而a和b访问的仍是自己定义的局部变量a,因为同名时,局部变量优先于全局变量。 <br />
但这里,问题又来了,为了在匿名函数间通信而大量添加全局变量也是不可取的,怎么办,我们这里可以借用面向对象的封装原则,声明一个hash变量用为全局变量,这个hash变量类似于一个集合,可以在这个集合中添加多个要用的变量。
</body>
</html>
如果要共享的数据很多,就会造成定义了大量的全局变量的局面,最后会导致不可控。
解决方案: 将多个全局变量包装在一起,使用一个hash全局变量,类似于一个集合一样的用。
代码语言:javascript复制<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>使用hash变量作为全局变量</title>
<script>
//hash全局变量
var GLOBAL={};
</script>
<script>
( function(){
//程序员a写的代码
var a=123;
alert( a);
})();
</script>
</head>
<body>
<script>
( function(){
//程序员b写的代码:操作全局GLOBAL变量
GLOBAL.a=89;
alert( "程序员b:" GLOBAL.a);
})();
</script>
<script>
( function(){
//程序员c写的代码访问的就是全局变量
alert( "程序员c:" GLOBAL.a);
})();
</script>
在这里使用了GLOBAL作为全局变量名, 在匿名函数间要传递值的话,将这些变量作为全局变量的属性即可。 <br />
但GLOBAL是全局变量,它在各个函数间都可以访问到,这很容易让GLOBAL的属性不小心被覆盖掉。 <br />
解决方案:<br />
命名空间
</body>
</html>
但GLOBAL是一个全局变量,各个函数都可以操作,很容易发生误操作。
代码语言:javascript复制<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>全局变量中添加命名空间的定义</title>
<script>
//hash全局变量
var GLOBAL={};
</script>
<script>
( function(){
//程序员a写的代码
GLOBAL.A={}; //程序员a定义了自己的命名空间
GLOBAL.A.a=123;
alert( GLOBAL.A.a);
})();
</script>
</head>
<body>
<script>
( function(){
//程序员b写的代码:操作全局GLOBAL变量
GLOBAL.a=89;
alert( "程序员b:" GLOBAL.a);
GLOBAL.B={}; //定义了自己的命名空间,现在只要保证命名空间不冲突即可。
GLOBAL.B.b=222;
alert("程序员b操作自己的命名空间下的变量:" GLOBAL.B.b );
GLOBAL.A.a=333;
alert( "程序员b操作A命名空间下的变量:" GLOBAL.A.a);
})();
</script>
<script>
( function(){
//程序员c写的代码
GLOBAL.A.b=444;
alert( "程序员c操作A命名空间下的变量:" GLOBAL.A.a);
alert( "程序员c操作A命名空间下的变量:" GLOBAL.A.b);
})();
</script>
另外,命名空间的也可以嵌套定义。 <br />
最后,再将定义命名空间的功能封装成一个函数。
</body>
</html>
最后将定义命名空间的功能封装成一个函数。
代码语言:javascript复制<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>全局变量GLOBAL中添加定义命名空间的函数</title>
<script>
//hash全局变量
var GLOBAL={};
// str :表示要生成的命名空间,例如: GLOBAL.A.name 或是 A.name
GLOBAL.namespace=function(str){
var arr=str.split(".");
var o=GLOBAL;
var i= (arr[0]=="GLOBAL"?1:0 ); //如果str中的第一部分为GLOBAL的话,命名空间从第二个开始计算
for( ;i<arr.length;i ){
o[arr[i]]=o[arr[i]]||{};
o=o[arr[i]];
}
}
</script>
<script>
( function(){
//程序员a写的代码
GLOBAL.namespace("A.person"); //程序员a定义了自己的命名空间A,并在A下面定义了子命名空间person
GLOBAL.A.person.name="zy";
GLOBAL.A.person.age=22;
alert( GLOBAL.A.person.name "t" GLOBAL.A.person.age);
})();
</script>
</head>
<body>
<script>
( function(){
//程序员b写的代码:定义自己的命名空间
GLOBAL.namespace("B.student"); //程序员a定义了自己的命名空间B,并在B下面定义了子命名空间student
GLOBAL.B.student.name="lisi";
GLOBAL.B.student.age=33;
alert( GLOBAL.B.student.name "t" GLOBAL.B.student.age);
})();
</script>
<script>
( function(){
//程序员c写的代码
alert( "程序员c操作A命名空间下的变量:" GLOBAL.A.person.name "t" GLOBAL.A.person.age);
alert( "程序员c操作B命名空间下的变量:" GLOBAL.B.student.name "t" GLOBAL.B.student.age);
})();
</script>
以上体现的就是合理使用命名空间解决变量冲突的问题。
</body>
</html>