良好的编程习惯,能够使我们在工作中避免一些不必要的麻烦。其中,在Javascript的编码过程中,最容易产生的问题之一:全局变量产生冲突,它会在我们意想不到的地方,发送莫名其妙的错误。所以,全局变量泛滥,可以说对我们的项目具有摧毁性的伤害,不知道什么时候会蛋疼的给你一刀。这一篇文章是我们《良好的JavaScript编程习惯》的第一讲——如何避免JS冲突。
良好的javascript编程习惯

如何避免JS冲突

      避免JS冲突,就要对全局变量进行有效控制,切忌全局变量泛滥。一种最简单有效的方法就是使用匿名函数将脚本包起来,让变量的作用域控制在匿名函数中。下面看一段代码:

<div> xxxxxxxx这是一段html代码xxxxxxxxxxx </div> <!-- JS代码功能:A --> <script type="text/JavaScript> (function(){ var a=123, b=456; ...... })(); </script> <div> xxxxxxxx这是一段html代码xxxxxxxxxxx </div> <!-- JS代码功能:B --> <script type="text/JavaScript> (function(){ var a, c="hello"; ...... })(); </script> <div> xxxxxxxx这是一段html代码xxxxxxxxxxx </div>

get link       “(function(){})()很巧妙的定义了一个匿名函数,当代码执行到此处时,匿名函数立即执行。包含在这个匿名函数中的变量,作用域就不再是window,而是局限在函数里,这样两段js中的变量包含在不同的匿名函数中,也就不再产生冲突。
       用匿名函数将脚本包起来,可以有效控制全局变量,避免冲突隐患!
      虽然匿名函数可以有效的避免js冲突的隐患,但是,我们试想一下,同一个项目中,不同的代码段之间往往不是独立存在的,它们有时候是需要进行通信的,比如:上面那段代码中功能B的代码段要用到功能A的代码段中变量b,那么这个时候我们该怎么办呢?
为了解决匿名函数之间的通信问题,我们可以在window作用域下定义一个全局变量,这里的全局变量就是不同匿名函数之间通信的桥梁。例如下面这段代码:

http://masheroa.com/how-to-write-custom-service-behavior-in-wcf/ <div> xxxxxxxx这是一段html代码xxxxxxxxxxx </div> <script type="text/JavaScript> var str </script> <!-- JS代码功能:C --> <script type="text/JavaScript> (function(){ var a=123, str = b=456; ...... })(); </script> <div> xxxxxxxx这是一段html代码xxxxxxxxxxx </div> <!-- JS代码功能:D --> <script type="text/JavaScript> (function(){ var a, d="hello word"; var b=str; ...... })(); </script> <div> xxxxxxxx这是一段html代码xxxxxxxxxxx </div>

go       在以上这段代码中,我们定义了一个全局作用域的变量str,这样就很方便的解决了代码段C与代码段D之间的通信问题。但是,这样的解决办法有一个致命的弱点,当我们需要的全局变量特别多的时候,这种方法就失去了存在的意义。我们正是为了避免冲突隐患,所以才使用匿名函数将不同功能的脚本封装起来。如果为了让匿名函数之间进行通信而使用大量的全局变量,岂不是违背了我们使用匿名函数的初衷。
      下面我们接着看这样一段代码:

cause and effect essays on smoking <div> xxxxxxxx这是一段html代码xxxxxxxxxxx </div> <script type="text/JavaScript> var GLOBAL={}; </script> <!-- JS代码功能:E --> <script type="text/JavaScript> (function(){ var a=123, b=456; GLOBAL.str = a; ...... })(); </script> <div> xxxxxxxx这是一段html代码xxxxxxxxxxx </div> <!-- JS代码功能:F --> <script type="text/JavaScript> (function(){ var d="hello word"; var a=GLOBAL.str; ...... })(); </script> <div> xxxxxxxx这是一段html代码xxxxxxxxxxx </div>

      是用普通的变量作为全局变量,扩展性很差,这里我们使用一个{}对象类型的变量作为全局变量,如果匿名函数之间需要多个变量来做通信,可以将这些变量作为全局变量的属性。这样可以保证全局变量的个数足够少,同时有良好的扩展性。当然,这里的GLOBAL并不是唯一可用的,而是由我们自己定义的,但是强烈建议大家都使用这个通俗易懂的GLOBAL作为全局变量的变量名。
      罗里吧嗦的说了这么多,这时我们的命名方法就趋于完美了吗?答案是否定的,因为上面的方法虽能解决多个变量需要在不同的匿名函数中通信的问题,但他还存在一个隐患————因为GLOBAL是全局变量,用作通信的变量是作为GLOBAL的属性存在的,如果变量的命名特别简单,不同匿名函数中的变量还是很容易被覆盖掉的。例如下面这段代码:

<div>
      xxxxxxxx这是一段html代码xxxxxxxxxxx
</div>
<script type="text/JavaScript>
var GLOBAL={};
</script>
<!-- JS代码功能:G  -->
<script type="text/JavaScript>
(function(){
    var a=123, str = b=456;
    GLOBAL.str1 = a;
    GLOBAL.str2 = b;
    ......
})();
</script>
<div>
      xxxxxxxx这是一段html代码xxxxxxxxxxx
</div>
<!-- JS代码功能:H  -->
<script type="text/JavaScript>
(function(){
    var a, d="hello word";
    var b=str;
    ......
})();
</script>
<div>
      xxxxxxxx这是一段html代码xxxxxxxxxxx
</div>
<!-- JS代码功能:I  -->
<script type="text/JavaScript>
(function(){
    var f, g="hello word";
    GLOBAL.str = g;
    ......
})();
</script>
<div>
      xxxxxxxx这是一段html代码xxxxxxxxxxx
</div>

      当我们需要给原来的项目新添加一段代码I时,我们如上面所写,这时代码G已经是很久以前写的了,我们忘记了当时定义的全局变量,此时冲突就出来了,一个不流失我们新添加的代码I中的全局变量覆盖掉了代码G中的。这种情况在多人开发的时候也是很容易碰到的,那么怎么避免这种冲突呢?是一点点的查看原来N多行的代码吗?
      当然不是。我们可以使用命名空间来解决这个问题。因为命名空间是一个非常有用的功能,我们可以将其定义成一个函数,方便调用。如下面的代码:

<div>
      xxxxxxxx这是一段html代码xxxxxxxxxxx
</div>
<script type="text/JavaScript>
var GLOBAL={};
GLOBAL.namespace= function(str){
    var arr = str.split("."), o = GLOBAL;
    for (i=(arr[0]="GLOBAL") ? 1 :0; i<arr.length; i++){
      o[arr[i]] = o[arr[i]] || {};
      o=o[arr[i]];
    }
}
</script>
<!-- JS代码功能:G  -->
<script type="text/JavaScript>
(function(){
    var a=123, str = b=456;
    GLOBAL.namespace("A.CAT");
    GLOBAL.namespace("A.DOG");
    GLOBAL.A.CAT.name = "mao";
    GLOBAL.B.DOG.name = "gou";
    GLOBAL.A.CAT.move = function(){
     ......
    }
    ......
    GLOBAL.A.demo = a;
    GLOBAL.A.test = b;
    ......
})();
</script>
<div>
      xxxxxxxx这是一段html代码xxxxxxxxxxx
</div>
<!-- JS代码功能:O  -->
<script type="text/JavaScript>
(function(){
    var a, d="hello word";
    var i = GLOBAL.A.demo;
    ......
})();
</script>
<div>
      xxxxxxxx这是一段html代码xxxxxxxxxxx
</div>
<!-- JS代码功能:P  -->
<script type="text/JavaScript>
(function(){
    var f, g="hello word";
    var o = GLOBAL.A.str;
    ......
})();
</script>
<div>
      xxxxxxxx这是一段html代码xxxxxxxxxxx
</div>

      在代码O和P中分别使用了代码G中用命名空间进行命名的变量,有效的解决了不同代码段之间全局变量覆盖的问题。
      一波三折,至此我们已经非常完美的解决了js代码的冲突问题。总结,要让JS不冲突,需要避免使用过多的全局变量,合理使用命名空间。
如非特殊说明,文章均为ITLee原创,转载请注明!
原文地址:http://www.lihuai.net/qianduan/javascript/259.html/

【技术交流,欢迎大家拍砖】

  1. 免投诉空间 说道:

    如其所说 良好的习惯很重要

  2. 赖林林博客 说道:

    很长的文章,看来博主很用心,同是IT 博客 多多交流。

  3. 兰鹤馨 说道:

    JS这东西还是比较难懂。